问题
I have two different JSONs and I would like to remove streets from the JSON object if only it exists under Address which is an array. I am trying to do this in powershell. I can get my script working and remove the streets but I only want to run the exclude line of command if the address has the streets property.
{
"Customer": [{
"id": "123"
}],
"address": [{
"$type": "Home",
"name": "Houston",
"streets": [{
"name": "Union",
"postalCode": "10"
}]
},
{
"$type": "Office",
"name": "Hawai",
"streets": [{
"name": "Rock",
"postalCode": "11"
}]
}
]
}
2nd JSON - Do not want to run the exclude line for 2nd JSON because there are no streets
{
"Customer": [{
"id": "123"
}],
"address": [{
"$type": "Home",
"name": "Houston"
},
{
"$type": "Office",
"name": "Hawai"
}
]
}
Powershell script
$FileContent = Get-Content -Path "Test.json" -Raw | ConvertFrom-Json
#Only want to run for address objects that contains streets
$FileContent.address = $FileContent.address | Select-Object * -ExcludeProperty streets #Only run for 1st json and not for 2nd json
$FileContent | ConvertTo-Json
回答1:
If you want to execute the code only if
the address
has the member
streets
you can test for just that:
if (
($FileContent.address | Get-Member -MemberType NoteProperty -Name "streets") -ne $null
){
$FileContent.address = $FileContent.address | Select-Object * -ExcludeProperty streets
}
回答2:
T-Me's helpful answer is the most robust approach, because it looks for the presence of the property itself rather than non-null values.
If you're willing to assume that the absence of a value also means the absence of the property itself, you can take the following shortcut, which performs better:
$hasAtLeastOneStreet = 0 -ne
(@((Get-Content Test.json -Raw | ConvertFrom-Json).address.streets) -ne $null).Count
.address.streets
uses member enumeration to extract all streets
values, @(...)
ensures that the result is an array, -ne $null
filters out any $null
values from that array, and .Count
counts its elements.
Note: This expression should be simpler:$null -ne (Get-Content Test.json -Raw | ConvertFrom-Json).address.streets
but due to a bug currently cannot - see the bottom section.
To demonstrate (the input strings are compressed, single-line versions of your JSON documents):
'{"Customer":[{"id":"123"}],"address":[{"$type":"Home","name":"Houston","streets":[{"name":"Union","postalCode":"10"}]},{"$type":"Office","name":"Hawai","streets":[{"name":"Rock","postalCode":"11"}]}]}',
'{"Customer":[{"id":"123"}],"address":[{"$type":"Home","name":"Houston"},{"$type":"Office","name":"Hawai"}]}' |
foreach {
"has street values: " +
(0 -ne @(((ConvertFrom-Json $_).address.streets) -ne $null).Count)
}
The above yields, showing that the first JSON document had street
values, whereas the second one did not.
has street values: True
has street values: False
Note: You should be able to simplify the test expression to the following, but this doesn't work due to a bug present up to at least PowerShell 7.0:
# !! SHOULD worm, but as of PowerShell 7.0, DOESN'T, due to a bug relating
# to the presence of two or more [pscustomobject] instances in the address array:
$hasAtLeastOneStreet =
$null -ne (Get-Content Test.json -Raw | ConvertFrom-Json).address.streets
Normally, the absence of any streets
property values should result in $null
, but with two or more [pscustomobject]
instances present in the .address
array, an array of $null
values is unexpectedly returned.
See GitHub issue #13752.
来源:https://stackoverflow.com/questions/64227185/exclude-the-json-property-only-if-it-exists-powershell