我试图在PowerShell中遍历以下JSON文件。
如果没有专门命名顶部标签(例如17443和17444),因为我事先并不知道它们,所以我找不到找到遍历数据的方法。
我想为所有记录输出标签3、4和5(标题,名字,姓氏)。
我该怎么做?
{
"17443":{
"sid":"17443",
"nid":"7728",
"submitted":"1436175407",
"data":{
"3":{
"value":[
"Mr"
]
},
"4":{
"value":[
"Jack"
]
},
"5":{
"value":[
"Cawles"
]
}
} },
"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"
]
}
}
}
}
我可以使用下面的代码访问数据,但我想避免放入17443、17444等。
$data = ConvertFrom-Json $json
foreach ($i in $data.17443)
{
foreach ($t in $i.data.3)
{
Write-Host $t.value
}
foreach ($t in $i.data.4)
{
Write-Host $t.value
}
foreach ($t in $i.data.5)
{
Write-Host $t.value
}
}
在PowerShell 3.0及更高版本中(请参阅:确定已安装的PowerShell版本),可以使用ConvertFrom-Json
cmdlet将JSON字符串转换为PowerShell数据结构。
这既方便又不幸-方便,因为它很容易使用JSON,不幸的是,由于ConvertFrom-Json
给了您PSCustomObjects,它们很难作为键值对进行迭代。
当您知道键之后,就没有什么要迭代的了–您只需直接访问它们,例如$result.thisKey.then.thatKey.array[1]
,就可以完成。
但在此特定的JSON中,键似乎是动态的/提前未知,例如"17443"
或"17444"
。这意味着我们需要一些可以变成可以理解PSCustomObject
的键值列表的东西foreach
。
# helper to turn PSCustomObject into a list of key/value pairs
function Get-ObjectMember {
[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-ObjectMember | foreach {
$_.Value | Get-ObjectMember | 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
}
}
}
输出
标题名姓 ----- --------- -------- 夏洛特·坦恩小姐 约翰·布罗克兰先生
另一种适用于PowerShell 2.0(不支持上述某些构造)的替代方法将涉及使用.NET JavaScriptSerializer类来处理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
}
}
}
输出是相同的:
标题名姓 ----- --------- -------- 夏洛特·坦恩小姐 约翰·布罗克兰先生
如果JSON大于4 MB,请相应地设置JavaScriptSerializer.MaxJsonLength
属性。
如果您从文件中读取,请使用Get-Content -Raw -Encoding UTF-8
。
-Raw
因为否则Get-Content
返回一个单独行的数组,JavaScriptSerializer.DeserializeObject
将无法处理。最新的Powershell版本似乎对.NET函数参数进行了改进的类型转换,因此它可能不会在您的系统上出错,但如果可以(或为了安全起见)使用-Raw
。-Encoding
因为在阅读时指定文本文件的编码是明智的做法,并且这UTF-8
是JSON文件最可能的值。{items: [{key: 'A', value: 0}, {key: 'B', value: 1}]}
over这样的数组结构{'A': 0, 'B': 1}
。后者似乎更直观,但既难以生成又难以使用。ConvertFrom-Json()
为您提供一个PSCustomObject
可反映JSON字符串中数据的PowerShell自定义对象()。Get-Member -type NoteProperty
$object."$propName"
语法或动态地访问对象的属性$object."$(some PS expression)"
。New-Object PSObject -Property @{...}
,或[PSCustomObject]@{ .. }
`本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句