使用 jmespath 对部分缺失的数组进行排序

Sorting partially missing arrays with jmespath

我正在尝试按 outer_name 对源数据 outeractivities 排序,然后按 activitiesinner_name:

Sourcedata.json:

[
    {
        "outeractivities": [
            {
                "outer_name": "2"
            },
            {
                "outer_name": "1",
                "activities": [
                    {
                        "inner_name": "B"
                    },
                    {
                        "inner_name": "A"
                    }
                ]
            }
        ]
    }
]

预期输出:

[
    {
        "outeractivities": [
            {
                "activities": [
                    {
                        "inner_name": "A"
                    },
                    {
                        "inner_name": "B"
                    }
                ],
                "outer_name": "1"
            },
            {
                "outer_name": "2"
            }
        ]
    }
]

通过使用

cat Sourcedata.json | jp "[].{outeractivities:sort_by(outeractivities[]. \
{outer_name:outer_name, activities:sort_by(activities[].{inner_name:inner_name},&inner_name) \
},&outer_name)  \
}"

我会得到异常:

Error evaluating JMESPath expression: Invalid type for: <nil>, expected: []jmespath.jpType{"array"}

如果我改变

{
          "outer_name": "2"
}

{
          "outer_name": "2",
          "activities": []
}

确实有效。
我该如何解决这个问题?

由于错误是由于 sort_by 在要排序的 属性 不存在时无法正确处理而发生的,因此您可以做的是列出两个列表:

  • 具有 activities 属性 的所有 outeractivities,按此字段排序
  • 所有 outeractivities 没有 activities 属性

然后,flatten 那两个列表。

鉴于查询:

[].{ 
  outeractivities: sort_by(
    [
      outeractivities[?activities == null], 
      outeractivities[?activities != null].{ 
        outer_name: outer_name, 
        activities: sort_by(activities, &inner_name)
      }
    ] [], 
    &outer_name
  )
}

这会产生预期的结果:

[
  {
    "outeractivities": [
      {
        "outer_name": "1",
        "activities": [
          {
            "inner_name": "A"
          },
          {
            "inner_name": "B"
          }
        ]
      },
      {
        "outer_name": "2"
      }
    ]
  }
]