的PowerShell 3.0
在PowerShell中3.0和更高版本可以使用ConvertFrom-Json
cmdlet來轉換一個JSON字符串轉換爲PowerShell數據結構。
這很方便,同時也很不方便 - 因爲它非常容易消耗JSON,不幸因爲ConvertFrom-Json
給你PSCustomObjects,而且它們很難作爲鍵值對迭代。
在這個特定的JSON中,按鍵似乎是動態/未知的,例如"17443"
或"17444"
。這意味着我們需要一些可以將PSCustomObject
轉換爲foreach
可以理解的鍵值列表。
# helper to turn PSCustomObject into a list of key/value pairs
function Get-ObjectMembers {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True)]
[PSCustomObject]$obj
)
$obj | Get-Member -MemberType NoteProperty | ForEach-Object {
$key = $_.Name
[PSCustomObject]@{Key = $key; Value = $obj."$key"}
}
}
現在我們可以遍歷對象圖,併產生輸出的對象的列表與Title
,FirstName
和LastName
$json = '{"17443": {"17444": {"sid": "17444","nid": "7728","submitted": "1436891400","data": {"3": {"value": ["Miss"]},"4": {"value": ["Charlotte"]},"5": {"value": ["Tann"]}}},"17445": {"sid": "17445","nid": "7728","submitted": "1437142325","data": {"3": {"value": ["Mr"]},"4": {"value": ["John"]},"5": {"value": ["Brokland"]}}},"sid": "17443","nid": "7728","submitted": "1436175407","data": {"3": {"value": ["Mr"]},"4": {"value": ["Jack"]},"5": {"value": ["Cawles"]}}}}'
$json | ConvertFrom-Json | Get-ObjectMembers | foreach {
$_.Value | Get-ObjectMembers | where Key -match "^\d+$" | foreach {
[PSCustomObject]@{
Title = $_.value.data."3".value | select -First 1
FirstName = $_.Value.data."4".value | select -First 1
LastName = $_.Value.data."5".value | select -First 1
}
}
}
輸出
Title FirstName LastName
----- --------- --------
Miss Charlotte Tann
Mr John Brokland
PowerShell的2.0 /替代做法
也適用於PowerShell 2.0(不支持上面的某些構造)的替代方法將涉及使用。NET JavaScriptSerializer class處理JSON:
Add-Type -AssemblyName System.Web.Extensions
$JS = New-Object System.Web.Script.Serialization.JavaScriptSerializer
現在我們可以做一個非常類似的操作 - 甚至有點簡單,因爲上面,因爲JavaScriptSerializer給你定期Dictionaries,這很容易遍歷經由鍵值對的GetEnumerator()方法:
$json = '{"17443": {"17444": {"sid": "17444","nid": "7728","submitted": "1436891400","data": {"3": {"value": ["Miss"]},"4": {"value": ["Charlotte"]},"5": {"value": ["Tann"]}}},"17445": {"sid": "17445","nid": "7728","submitted": "1437142325","data": {"3": {"value": ["Mr"]},"4": {"value": ["John"]},"5": {"value": ["Brokland"]}}},"sid": "17443","nid": "7728","submitted": "1436175407","data": {"3": {"value": ["Mr"]},"4": {"value": ["Jack"]},"5": {"value": ["Cawles"]}}}}'
$data = $JS.DeserializeObject($json)
$data.GetEnumerator() | foreach {
$_.Value.GetEnumerator() | where { $_.Key -match "^\d+$" } | foreach {
New-Object PSObject -Property @{
Title = $_.Value.data."3".value | select -First 1
FirstName = $_.Value.data."4".value | select -First 1
LastName = $_.Value.data."5".value | select -First 1
}
}
}
輸出是一樣的:
Title FirstName LastName
----- --------- --------
Miss Charlotte Tann
Mr John Brokland
如果你從文件中讀取,使用Get-Content -Raw -Encoding UTF-8
。
-Raw
因爲否則Get-Content
返回各條線的陣列,並且JavaScriptSerializer.DeserializeObject
無法處理。最近的Powershell版本似乎改進了.NET函數參數的類型轉換,所以它可能不會在您的系統上出錯,但如果它確實(或者只是爲了安全起見),請使用-Raw
。
-Encoding
因爲在讀取文本文件時指定文本的編碼是明智的,UTF-8
是JSON文件最可能的值。
如果您的JSON文件大於4 MB,請相應地設置JavaScriptSerializer.MaxJsonLength
property。
注
ConvertFrom-Json()
爲您提供了一個PowerShell自定義對象(PSCustomObject
)反映在JSON字符串的數據。
- 您可以循環雖然自定義對象的與
Get-Member -type NoteProperty
- 屬性可以動態地使用
$object."$propName"
語法,或者$object."$(some PS expression)"
訪問一個對象的屬性。
- 您可以創建自己的自定義對象,並與
New-Object PSObject -Property @{...}
一堆屬性初始化它,或者[PSCustomObject]@{ .. }
`
你有你自己嘗試新鮮事物或者是你在等待有人實現了這個要求? – Tomalak
是的,我可以專門增加頂部的標籤,如 的foreach($ I $中data.17443) { 的foreach($在$ i.data.3 T) { 寫主機獲取數據$ t.value } 的foreach(在$ $ i.data.4 T) { 寫主機$ t.value } 的foreach(在$ $ i.data.5 T) { 寫主機$ t.value } } – Omen9876
我用這個編輯了我的問題,所以它更有幫助 – Omen9876