在PowerShell中了解NewtonSoft

潜水员丹

至少可以说,我涉足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?

我希望能够找到任何给定位置的根父级名称。因此,在上面,我想知道我正在查看的项目(Array2Object1Str1)属于Array2根父级。

我认为我在这里不了解一些基本知识。是否可以确定根父级?另外,对理解我在脚本中的注释的任何帮助都将非常有用。这就是为什么我无法返回诸如path或parent之类的东西,但是在VSCode中进行调试时却可以看到它的原因。

mklement0

dbc的答案包含有用的背景信息,并且清楚地表明从PowerShell调用NewtonSoft Json.NET库很麻烦。

鉴于PowerShell对JSON解析的内置支持(通过ConvertFrom-JsonConvertTo-Jsoncmdlet)通常没有理由诉诸第三方库(直接[1]),在以下情况下除外

  • 性能至关重要时。
  • 必须克服PowerShell JSON解析限制时(缺少对空键名和仅字母大小写不同的键的支持)。
  • 当您需要使用Json.NET类型及其方法,而不是使用无方法的“属性袋”[pscustomobject]实例ConvertFrom-Json构造时。

虽然与NewtonSoft的Json.NET直接在PowerShell中的工作是尴尬的,它是可管理的,如果你遵循以下几条规则

  • 缺乏可见的输出并不一定意味着根本没有任何输出

    • 由于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

      • 由于另一个错误(可能具有相同的根本原因),自PowerShell Core 7.0.0-preview.4起,在输入JSON包含数组的情况下,[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的array-subexpression运算符,它强制[JObject]实例的枚举产生其[JProperty]成员数组,然后可以通过索引对其进行访问;请注意,这种方法很简单,但是效率不高,因为枚举和构造了aux。发生阵列;但是,鉴于单个JSON对象(而不是array)通常不具有大量属性,因此在实践中这不太可能重要。
      一种基于反射的解决方案可以访问该IList<JToken>接口的数字索引器,但可能更慢。

    • 请注意,.Value可能再次需要基于附加的访问来打印结果(或提取强类型属性)。

  • 通常,不要使用该.GetEnumerator()方法[JObject]并且[JArray]实例是直接枚举的

    • 请记住,PowerShell可能会在您不期望的上下文中自动枚举此类实例,尤其是在管道中值得注意的是,当您将a发送[JObject]到管道时,它的组成部分[JProperty]是单独发送的
  • 使用类似@($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())"
}

[1] PowerShell Core-但不是Windows PowerShell-当前(v7)实际上在幕后使用NewtonSoft的Json.NET。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在Hibernate中了解@BatchSize

来自分类Dev

在Swift中了解Singleton

来自分类Dev

在AST中了解ctx

来自分类Dev

在javascript中了解“ this”的问题

来自分类Dev

在dmesg中了解时间

来自分类Dev

在dmesg中了解时间

来自分类Dev

在RustLang中了解Box :: leak()。into()

来自分类Dev

在Scala中了解Spark中的功能文档

来自分类Dev

从字典中了解选择器

来自分类Dev

在解析器组合器中了解`not`

来自分类Dev

在Swift中了解崩溃报告(部分应用...)

来自分类Dev

如何在autoconf中了解AS_IF

来自分类Dev

在Solr中了解文档的索引时间

来自分类Dev

如何从提交中了解表格

来自分类Dev

在SQL中了解表的结构/架构

来自分类Dev

基本-从Doctrine查询中了解PHP对象

来自分类Dev

如何在autoconf中了解AS_IF

来自分类Dev

在Solr中了解文档的索引时间

来自分类Dev

在此示例中了解R语法

来自分类Dev

在Scala中了解Spark中的功能文档

来自分类Dev

在Angular 2教程中了解HTTP

来自分类Dev

在Hapi.js Restful API中了解请求IP

来自分类Dev

如何在TensorFlow中了解静态形状和动态形状?

来自分类Dev

在Julia中了解没有基本案例的递归

来自分类Dev

不确定我在Haskell中了解这种类型

来自分类Dev

在正则表达式中了解\ G和\ K

来自分类Dev

在Couchbase Lite android中了解已删除的文档

来自分类Dev

如何在URL处理程序中了解Tornado的字典?

来自分类Dev

在我的ReactiveCocoa测试项目中了解ReactiveCocoa和MVVM