PowerShell 3.0+
在 PowerShell 3.0 及更高版本中(请参阅:确定安装的 PowerShell 版本),您可以使用ConvertFrom-Json
cmdlet 将 JSON 字符串转换为 PowerShell 数据结构。
这既方便又不幸——方便,因为它很容易使用 JSON,不幸的是因为ConvertFrom-Json
它给了你PSCustomObjects,并且它们很难作为键值对进行迭代。
当您知道密钥时,就没有什么可以迭代的了——您只需直接访问它们,例如$result.thisKey.then.thatKey.array[1]
,就完成了。
但是在这个特定的 JSON 中,键似乎是动态的/提前不知道的,例如"17443"
or "17444"
。这意味着我们需要一些可以将 a转换为可以理解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 / 替代方法
也适用于 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
属性。
从文件中读取 JSON
如果从文件中读取,请使用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}]}
当您构建包含具有不可预知键的项目的 JSON 时,更喜欢像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]@{ .. }
`