只有 remove/Exclude 来自 json 的属性(如果存在)

Only remove/Exclude an attribute from json if it exists

我有以下 JSON,我想从 JSON 对象中删除街道,前提是它存在于 Address 下,它是一个数组。我正在尝试在 powershell 中执行此操作。我可以让我的脚本工作并删除街道,但如果地址有街道 属性,我只想 运行 排除命令行。这可能吗?

{
    "Customer": [{
        "id": "123"
    }],
    "Nationality": [{
        "name": "US",
        "id": "456"
    }],
    "address": [{
            "$type": "Home",
            "name": "Houston",
            "streets": [{
                "name": "Union",
                "postalCode": "10"
            }]
        },
        {
            "$type": "Home5",
            "name": "Houston5"
        },
        {
            "$type": "Office",
            "name": "Hawai",
            "streets": [{
                "name": "Rock",
                "postalCode": "11"
            }]
        }
    ]
}

Powershell 脚本

$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 would like to run if object address has streets property
$FileContent | ConvertTo-Json

注:

  • 此答案执行与问题中相同的操作,只是在单个管道中更简洁。

  • 运行Select-Object * -ExcludeProperty streets对数组address中的所有对象是良性的,因为调用是一个对于那些已经缺少 streets 属性 的对象有效 no-op(尽管也创建了此类对象的 copy)。


你需要一个赋值来修改你的对象in-place然后输出它们,这需要一个ForEach-Object通话:

Get-Content -Raw Test.json | ConvertFrom-Json | 
  ForEach-Object { 
    [array] $_.address = $_.address | select * -exclude streets; $_ 
  }

请注意从 JSON 输入解析的每个对象如何首先通过赋值 ($_.address = ...) 进行修改,然后传递出去 ($_)。

一个更高效但更晦涩的变体:

Get-Content -Raw Test.json | ConvertFrom-Json | 
  ForEach-Object { 
    $_.address.ForEach({ $_.psobject.Properties.Remove('streets') }); $_ 
  }

使用您的示例 JSON 输入,两个命令输出如下:

Customer    Nationality          address
--------    -----------          -------
{@{id=123}} {@{name=US; id=456}} {@{$type=Home; name=Houston}, @{$type=Home5; name=Houston5}, @{$type=Office; name=Hawai}}

请注意 address 列中的对象如何不再具有 streets 属性。

警告:请注意ConvertTo-Json limits the serialization depth to 2 by default, which is sufficient in this case, but in other cases you may have to pass a -Depth argument to prevent data loss - see .