考虑这两个JSON文件:

{
  "tables": [
    {
      "columns": [
        {
          "name": "action",
          "type": "string"
        },
        {
          "name": "region",
          "type": "string"
        },
        {
          "name": "count_",
          "type": "long"
        },
        {
          "name": "min_timestamp",
          "type": "datetime"
        },
        {
          "name": "max_timestamp",
          "type": "datetime"
        }
      ],
      "name": "PrimaryResult",
      "rows": [
        [
          "ChangePassword",
          "CN",
          1,
          "2022-07-19T11:51:52.8430729Z",
          "2022-07-19T11:51:52.8430729Z"
        ]
      ]
    }
  ]
}
{
  "tables": [
    {
      "columns": [
        {
          "name": "action",
          "type": "string"
        },
        {
          "name": "region",
          "type": "string"
        },
        {
          "name": "count_",
          "type": "long"
        },
        {
          "name": "min_timestamp",
          "type": "datetime"
        },
        {
          "name": "max_timestamp",
          "type": "datetime"
        }
      ],
      "name": "PrimaryResult",
      "rows": [
        [
          "ChangePassword",
          "CN",
          1,
          "2022-07-19T11:51:52.8430729Z",
          "2022-07-19T11:51:52.8430729Z"
        ],
        [
          "Register",
          "CN",
          1,
          "2022-07-19T11:51:52.8430729Z",
          "2022-07-19T11:51:52.8430729Z"
        ]
      ]
    }
  ]
}

它们具有完全相同的模式,并且几乎相同.不同之处在于,第一个文件在rows属性中有1行,第二个文件在rows属性中有2行.


我使用ConvertFrom-Json将文件加载到PowerShell.当我开始访问.tables.rows[0]时,我希望它将返回第一行.

然而,在只有一行的第一个文件中,它实际上返回第一行的第一列.

(gc file1.json | ConvertFrom-Json).tables.rows[0]

输出:

ChangePassword

如果第二个文件中有超过1行,则.tables.rows[0]的行为与预期相同.

(gc file2.json | ConvertFrom-Json).tables.rows[0]

输出:

ChangePassword
CN
1
2022-07-19T11:51:52.8430729Z
2022-07-19T11:51:52.8430729Z

我如何在PowerShell中可靠地处理这些JSON文件,而不管其中是一行还是多行?

顺便说一句,这些实际上是az cli生成的JSON文件,是Azure Application Insights查询的结果.

推荐答案

tl;dr

如果希望按原样访问集合值属性,则需要避免member-access enumeration,在您的情况下,这意味着以下内容,如nimizen在注释中所示:

# Note the [0] after .tables
# (-Raw was added for efficiency)
(gc -Raw file1.json | ConvertFrom-Json).tables[0].rows[0]

Because your tables property is itself an array, accessing just .tables results in member-access enumeration (even though the array happens to have just one element).
Using index [0] to target that one element explicitly allows access to its (one and only) .rows property without the latter's value being subject to implicit enumeration, as explained in the next section.


你看到的是surprising aspect of PowerShell's 100 feature:

从集合元素的成员获得的值被发出,就像它们被发送到pipelineone by one,这具有以下含义:

  • 与管道中的默认情况一样,如果恰好是集合值,则任何此类值都是enumerated,即逐个发出其elements.

  • accessing结果输出上,如果只有one个输出对象(无论它是否恰好是集合本身),则按原样捕获它;如果有two or more个,则隐式收集在常规PowerShell数组(类型[object[]])中.

upshot for enumerated member values that happen to contain collections是:

  • 输入集合themselves总是丢失,因为只有它们的elements被输出.

  • 如果有multiple个集合值成员值,那么最终将得到single, flat array个,总是[object[]]类型,即所有涉及集合的元素中的concatenation个.

  • 如果只有one个集合值的成员值,而该值恰好是single个元素的集合,那么最终将得到单个元素as-is(只有multiple个元素,最终将得到[object[]]个数组).

这一令人惊讶的行为是GitHub issue #6802的主题,但请注意,该行为不太可能改变,以免 destruct 向后兼容性.


simplified example分来演示您的 case :

注意:JSON是这个问题的附带问题,所以我在下面使用[pscustomobject]个实例.

# Construct a single-element array that has a [pscustomobject] element.
# whose .prop property contains a single-element array whose only
# element is another array, typed [int[]].
$array = , [pscustomobject] @{ prop = , [int[]] (1, 2) }

# Use member-access enumeration to access the .prop member value
# of all elements in the array (here, there's only one), and get
# the first element.
$array.prop[0] # !! -> scalar 1, i.e. the first elem. of the *nested* array,
               # !! because member-access enumeration *enumerated* the 
               # !! single-element outer array.

# Without member-access enumeration, the value of .prop is accessed as-is,
# as a nested array:
$array[0].prop[0] # -> [int[]] (1, 2), as expected.

Json相关问答推荐

Elasticsearch Go客户端错误:无效的SON格式:在中间件中索引文档时出错

为什么JQ筛选器不将原始输入打印为$var|.';文档?

简单条形图和有序分类中条形图的 colored颜色 梯度

GitHub Pages无法正确显示我的项目

使用 serde 和 csv crates 将嵌套的 json 对象序列化为 csv

添加到数组时出错:找不到Add的重载和参数计数:1

如何在 Android Studio 中将 List 字段作为空列表[]返回?

如何在 wso2 中组合 2 个 json 有效负载?

提交后使用 Rails 7 结合 JSON 标签进行标记

如何将西里尔字母转换为 utf16

如何使用 LINQ 在 C# 中重构对象?

为什么在测试 RSPEC 时 JBuilder 不返回 JSON 中的响应正文

解析包含换行符的 JSON

没有很多类的 GSON 解析

在 JSON 字符串中react i18n 换行符

读取 HttpwebResponse json 响应,C#

如何自动修复无效的 JSON 字符串?

如何将有向无环图 (DAG) 存储为 JSON?

将 javascript 对象或数组转换为 json 以获取 ajax 数据

Volley JsonObjectRequest Post 参数不再起作用