Scu*_*Dan 2 powershell json json.net
我涉足 JSON 解析和 NewtonSoft 的世界,至少可以说我很困惑。
使用以下 PowerShell 脚本:
$json = @"
{
"Array1": [
"I am string 1 from array1",
"I am string 2 from array1"
],
"Array2": [
{
"Array2Object1Str1": "Object in list, string 1",
"Array2Object1Str2": "Object in list, string 2"
}
]
}
"@
#The newtonSoft way
$nsObj = [Newtonsoft.Json.JsonConvert]::DeserializeObject($json, [Newtonsoft.Json.Linq.JObject])
$nsObj.GetType().fullname #Type = Newtonsoft.Json.Linq.JObject
$nsObj[0] #Returns nothing. Why?
$nsObj.Array1 #Again nothing. Maybe because it contains no key:value pairs?
$nsObj.Array2 #This does return, maybe because has object with kv pairs
$nsObj.Array2[0].Array2Object1Str1 #Returns nothing. Why? but...
$nsObj.Array2[0].Array2Object1Str1.ToString() #Cool. I get the string this way.
$nsObj.Array2[0] #1st object has a Path property of "Array2[0].Array2Object1Str1" Great!
foreach( $o in $nsObj.Array2[0].GetEnumerator() ){
"Path is: $($o.Path)"
"Parent is: $($o.Parent)"
} #??? Why can't I see the Path property like when just output $nsObj.Array2[0] ???
#How can I find out what the root parent (Array2) is for a property? Is property even the right word?
Run Code Online (Sandbox Code Playgroud)
我希望能够找到任何给定位置的根父级的名称。所以在上面,我想知道我正在查看的项目 (Array2Object1Str1) 属于 Array2 根父级。
我想我不了解这里的一些基本原理。是否可以确定根父级?此外,任何有助于理解我在脚本中的评论的帮助都会很棒。即为什么我不能返回诸如路径或父级之类的东西,但在 VSCode 中调试时可以看到它。
dbc 的回答包含有用的背景信息,并明确说明从 PowerShell 调用 NewtonSoft Json.NET 库很麻烦。
鉴于PowerShell的内置的JSON解析的支持-通过ConvertFrom-Json与ConvertTo-Jsoncmdlet的-有通常没有理由诉诸第三方库(直接[1] ),除以下情况:
[pscustomobject]实例ConvertFrom-Json构造时。虽然直接在 PowerShell 中使用 NewtonSoft 的 Json.NET 很尴尬,但它是可以管理的,如果您遵守一些规则:
缺乏可见输出并不一定意味着根本没有任何输出:
由于PowerShell 中的错误(从 v7.0.0-preview.4 开始),[JValue]实例和[JProperty]包含它们的实例默认不产生可见输出;改为访问他们的(强类型).Value属性(例如,$nsObj.Array1[0].Value或$nsProp.Value.Value(原文如此))
要输出的字符串表示一个的[JObject]/ [JArray]/ [JProperty]/[JValue]例如,不依赖原样输出(例如$nsObj),使用具有明确的字串.ToString()(例如,$nsObj.ToString()); 虽然字符串插值(例如,"$nsObj")通常可以工作,但[JValue]由于上述错误,它不适用于实例。
[JObject]和[JArray]对象默认显示其元素的实例属性列表(暗示Format-List应用于对象的枚举);您可以使用Format-*cmdlet 来调整输出;例如,$nsObj | Format-Table Path, Type。
[JObject]实例的默认输出实际上已损坏。format-default : Target type System.Collections.IEnumerator is not a value type or a non-abstract class. (Parameter 'targetType')要对[JObject]实例进行数字索引,即按索引而不是按名称访问属性,请使用以下习语:@($nsObj)[<n>],其中<n>是感兴趣的数字索引。
$nsObj[<n>]实际上应该可以工作,因为与 C# 不同,PowerShell 将通过接口实现的成员公开为可直接调用的类型成员,因此通过接口实现的数字索引器应该可以访问,但不能访问,大概是由于这个错误(从 PowerShell Core 7.0 开始) .0-preview.4)。JObjectIList<JToken>
基于@(...)PowerShell 的数组子表达式运算符的解决方法强制枚举[JObject]实例以生成其[JProperty]成员的数组,然后可以通过索引访问该数组;请注意,这种方法很简单,但效率不高,因为 aux 的枚举和构造。数组发生;然而,鉴于单个 JSON 对象(与数组相反)通常没有大量属性,这在实践中不太可能重要。
访问IList<JToken>接口的数字索引器的基于反射的解决方案是可能的,但可能更慢。
请注意,.Value可能再次需要额外的基于访问的访问来打印结果(或提取强类型属性值)。
一般不使用该.GetEnumerator()方法;[JObject]和[JArray]实例是直接可枚举的。
[JObject]到管道时,它的组成部分[JProperty]s 被单独发送。使用类似@($nsObj.Array1).Value提取值的数组的原始JSON值(字符串,数字,...) -即[JValue]实例-数组。
下面在上下文中演示了这些技术:
$json = @"
{
"Array1": [
"I am string 1 from array1",
"I am string 2 from array1",
],
"Array2": [
{
"Array2Object1Str1": "Object in list, string 1",
"Array2Object1Str2": "Object in list, string 2"
}
]
}
"@
# Deserialize the JSON text into a hierarchy of nested objects.
# Note: You can omit the target type to let Newtonsoft.Json infer a suitable one.
$nsObj = [Newtonsoft.Json.JsonConvert]::DeserializeObject($json)
# Alternatively, you could more simply use:
# $nsObj = [Newtonsoft.Json.Linq.JObject]::Parse($json)
# Access the 1st property *as a whole* by *index* (index 0).
@($nsObj)[0].ToString()
# Ditto, with (the typically used) access by property *name*.
$nsObj.Array1.ToString()
# Access a property *value* by name.
$nsObj.Array1[0].Value
# Get an *array* of the *values* in .Array1.
# Note: This assumes that the array elements are JSON primitives ([JValue] instances.
@($nsObj.Array1).Value
# Access a property value of the object contained in .Array2's first element by name:
$nsObj.Array2[0].Array2Object1Str1.Value
# Enumerate the properties of the object contained in .Array2's first element
# Do NOT use .GetEnumerator() here - enumerate the array *itself*
foreach($o in $nsObj.Array2[0]){
"Path is: $($o.Path)"
"Parent is: $($o.Parent.ToString())"
}
Run Code Online (Sandbox Code Playgroud)
[1] PowerShell Core - 但不是Windows PowerShell - 当前 (v7) 实际上在幕后使用 NewtonSoft 的 Json.NET。
| 归档时间: |
|
| 查看次数: |
2988 次 |
| 最近记录: |