遍历JSON文件PowerShell [英] Iterating through a JSON file PowerShell
问题描述
我正在尝试在PowerShell中遍历下面的JSON文件.
I am trying to loop through the below JSON file in PowerShell.
由于没有专门命名顶部标签(例如17443和17444),因为我事先并不知道它们,所以我找不到找到遍历数据的方法.
Without specifically naming the top tags (e.g. 17443 and 17444), as I do not know them in advance I cannot find a way to loop through the data.
我想为所有记录输出标签3、4和5(标题,名字,姓氏).
I want to output tags 3, 4 and 5 (title, firstname, surname) for all the records.
我该怎么做?
{
"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等.
I can access the data with the code below, but I want to avoid putting in 17443, 17444, etc.
$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 3.0及更高版本中(请参阅:确定已安装的PowerShell版本),您可以使用ConvertFrom-Json
cmdlet来转换将JSON字符串转换为PowerShell数据结构.
PowerShell 3.0+
In PowerShell 3.0 and higher (see: Determine installed PowerShell version) you can use the ConvertFrom-Json
cmdlet to convert a JSON string into a PowerShell data structure.
这既方便又不幸-方便,因为它很容易使用JSON,不幸的是,因为ConvertFrom-Json
为您提供
That's convenient and unfortunate at the same time - convenient, because it's very easy to consume JSON, unfortunate because ConvertFrom-Json
gives you PSCustomObjects, and they are hard to iterate over as key-value pairs.
在此特定的JSON中,键似乎是动态的/事先未知,例如"17443"
或"17444"
.这意味着我们需要能够将PSCustomObject
转换为foreach
可以理解的键值列表的东西.
In this particular JSON, the keys seem to be dynamic/not known ahead of time, like "17443"
or "17444"
. That means we need something that can turn a PSCustomObject
into a key-value list that foreach
can understand.
# 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
Now we can traverse the object graph and produce a list of output objects with Title
, FirstName
and 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
PowerShell 2.0 / Alternative approach
An alternative approach that also works for PowerShell 2.0 (which does not support some of the constructs above) would involve using the .NET JavaScriptSerializer class to handle the JSON:
Add-Type -AssemblyName System.Web.Extensions
$JS = New-Object System.Web.Script.Serialization.JavaScriptSerializer
现在,我们可以做一个非常类似的操作-比上面的操作更简单,因为JavaScriptSerializer为您提供常规的
Now we can do a very similar operation—even a bit simpler than above, because JavaScriptSerializer gives you regular Dictionaries, which are easy to iterate over as key-value pairs via the GetEnumerator()
method:
$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
If you have JSON larger than 4 MB, set the JavaScriptSerializer.MaxJsonLength
property accordingly.
如果您从文件中读取,请使用Get-Content -Raw -Encoding UTF-8
.
If you read from a file, use Get-Content -Raw -Encoding UTF-8
.
-
-Raw
,因为否则Get-Content
返回单个行的数组,而JavaScriptSerializer.DeserializeObject
无法处理.最新的Powershell版本似乎对.NET函数参数进行了改进的类型转换,因此它可能不会在您的系统上出错,但是如果这样做(或者为了安全起见),请使用-Raw
. -
-Encoding
是因为明智的做法是在读取文本文件时指定其编码,并且UTF-8
是JSON文件最可能的值.
-Raw
because otherwiseGet-Content
returns an array of individual lines andJavaScriptSerializer.DeserializeObject
can't handle that. Recent Powershell versions seem to have improved type-conversion for .NET function arguments, so it might not error out on your system, but if it does (or just to be safe), use-Raw
.-Encoding
because it's wise to specify a text file's encoding when you read it andUTF-8
is the most probable value for JSON files.
-
ConvertFrom-Json()
为您提供了一个PowerShell定制对象(PSCustomObject
),该对象反映了JSON字符串中的数据. - 您可以使用
Get-Member -type NoteProperty
遍历自定义对象的属性
- 您可以使用
$object."$propName"
语法或$object."$(some PS expression)"
语法动态访问对象的属性. - 您可以创建自己的自定义对象,并使用
New-Object PSObject -Property @{...}
或[PSCustomObject]@{ .. }
的一系列属性对其进行初始化. `
ConvertFrom-Json()
gives you a PowerShell custom object (PSCustomObject
) that reflects the data in the JSON string.- You can loop though the properties of a custom object with
Get-Member -type NoteProperty
- You can access the properties of an object dynamically using the
$object."$propName"
syntax, alternatively$object."$(some PS expression)"
. - You can create your own custom object and initialize it with a bunch of properties with
New-Object PSObject -Property @{...}
, alternatively[PSCustomObject]@{ .. }
`
这篇关于遍历JSON文件PowerShell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!