PowerShell 練習 - JSON 物件陣列差異比對
0 |
之前寫過比對兩個 JSON 物件陣列差異的 .NET 小工具,用來對照多哪幾筆、少哪幾筆,哪幾筆的哪幾個欄位不同。這回場景類似,但要改用 PowerShell 實現,當成暖身練習。
先準備測試資料如下,故意讓 src.json 與 dst.json 二者有一筆新增、一筆缺少、一筆相同、一筆欄位值不同。
src.json
[
{ "Key": "Same", "Text": "Consistent", "Code": 0 },
{ "Key": "Diff", "Text": "Original", "Code": 0 },
{ "Key": "Miss", "Text": "Missing", "Code": 0 }
]
dst.json
[
{ "Key": "Same", "Text": "Consistent", "Code": 0 },
{ "Key": "Diff", "Text": "Modified", "Code": 1 },
{ "Key": "New", "Text": "New Data", "Code": 1 }
]
一陣子沒寫 PowerShell,這回復習了幾個小技巧:
- ConvertFrom-Json 轉換出來的物件陣列要用括號包起來或存入變數才能正常跑 ForEach-Object/Where-Object。參考:PowerShell ConvertFrom-Json 還原陣列無法 Where-Object 篩選
- JSON 換成的自訂物件(PSCustomObject)可用 Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name 列舉屬性名稱字串。
PowerShell 自訂物件的屬性型別為 NoteProperty,例如以下範例:
- 要用字串變數當屬性名稱的寫法為 $custObject.$propName (不是 $custObject[$propName]):
程式範例如下:
param (
[Parameter(Mandatory=$true)]
[string]$srcPath,
[Parameter(Mandatory=$true)]
[string]$dstPath
)
$ErrorActionPreference = "Stop"
$src = @{}
# https://blog.darkthread.net/blog/ps-convertfrom-json-pipeline-issue/
# 使用 ( ) 包住 ConvertFrom-Json 結果以視為一般陣列處理
(Get-Content $srcPath | ConvertFrom-Json) | ForEach-Object { $src[$_.Key] = $_ }
$dst = @{}
(Get-Content $dstPath | ConvertFrom-Json) | ForEach-Object { $dst[$_.Key] = $_ }
# 找出 $dst 有但 $src 沒有的項目
$dst.Keys | Where-Object { !$src.ContainsKey($_) } | ForEach-Object {
Write-Host "多出: $($_)=$($dst[$_] | ConvertTo-Json)"
}
# 找出 $src 有但 $dst 缺少的項目
$src.Keys | Where-Object { !$dst.ContainsKey($_) } | ForEach-Object {
Write-Host "缺少: $($_)=$($src[$_] | ConvertTo-Json)"
}
# 找出 $src 與 $dst 有但值不同的項目
$src.Keys | Where-Object { $dst.ContainsKey($_) -and $src.ContainsKey($_)} | ForEach-Object {
# 比較兩物件的所有欄位找出差異 (假設二物件擁有相同欄位)
$key = $_
$srcObj = $src[$key]
$dstObj = $dst[$key]
$diff = @{}
# Get-Member 取得物件所有 NoteProperty (屬性) 並取出 Name (屬性名稱)
$src[$key] | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object {
$propName = $_
# 可以用變數當屬性名稱取值
if ($srcObj.$propName -ne $dstObj.$propName) {
$diff[$propName] = "$($srcObj.$propName) => $($dstObj.$propName)"
}
}
if ($diff.Count -gt 0) {
Write-Host "差異: $($_)=$($diff | ConvertTo-Json)"
}
}
筆記備用。
PowerShell example to compare two custom object array JSONs with PowerShell.
Comments
Be the first to post a comment