json jq -删除“带对象的对象数组”中的不匹配字段

fcipmucu  于 2022-12-15  发布在  其他
关注(0)|答案(2)|浏览(173)

给定以下JSON对象:

{
  "meta": {
    "data1": {
      "keep": { "key": "value" }
    }
  },
  "detail": {
    "data2": [
      {
        "keep1": "keep1value",
        "keep2": "keep2value",
        "nokeep1": "abc"
      }
    ],
    "data3": [
      {
        "keep1": "keep1value",
        "keep2": "keep2value",
        "nokeep2": { "abc": "def" }
      }
    ]
  },
  "drop" : "this"
}

我试图通过删除不需要的字段来清理它,如“remove”,“nokeep 1”和“nokeep 2”。然而,“data 2”和“data 3”数组中的对象可能包含比示例“nokeepX”更多的字段,但将始终包含我想保留的“keep 1”和“keep 2”。
我想要的输出是以下JSON:

{
    "meta": { "data1": { "keep": { "key": "value" } } },
    "detail": {
        "data2": [
            {
                "keep1": "keep1value",
                "keep2": "keep2value"
            }
        ],
        "data3": [
            {
                "keep1": "keep1value",
                "keep2": "keep2value"
            }
        ]
    }
}

我已经设法删除了“下降”字段与此查询:
jq 'def pick($paths): . as $root | reduce ($paths[]|[.]|flatten(1)) as $path ({}; . + setpath($path; $root|getpath($path))); pick([["meta"], ["detail", "data2"], ["detail", "data3"]])'
然而,我一直在努力找出如何删除“nokeepX”字段-有可能做到这一点吗?

tcomlyy6

tcomlyy61#

如果只有有限的属性集,则不删除不需要的字段,而仅从必需字段创建输出可能会更容易:

{
    meta,
    detail: .detail | {
        data2: .data2 | map({ keep1, keep2 }),
        data3: .data3 | map({ keep1, keep2 })
    }
}

输出:

{
  "meta": {
    "data1": {
      "keep": {
        "key": "value"
      }
    }
  },
  "detail": {
    "data2": [
      {
        "keep1": "keep1value",
        "keep2": "keep2value"
      }
    ],
    "data3": [
      {
        "keep1": "keep1value",
        "keep2": "keep2value"
      }
    ]
  }
}

该方法可以与删除某些字段相结合:

{
    meta,
    detail: .detail | {
        data2: .data2 | map(del(.nokeep1)),
        data3: .data3 | map(del(.nokeep2))
    }
}

产生与上述相同的输出。

8yparm6h

8yparm6h2#

只需提供del的所有具体路径:

del(
  .detail.data2[0].nokeep1,
  .detail.data3[0].nokeep2,
  .drop
)

Demo
或者通过例如使用没有索引的[]遍历所有数组项(不仅仅是第一项)来进行泛化:

del(
  .detail.data2[].nokeep1,
  .detail.data3[].nokeep2,
  .drop
)

Demo
或者使用..进行任意深度搜索,只需提供最深的字段名称:

del(.. | objects | .nokeep1, .nokeep2, .drop)

Demo
输出:

{
  "meta": {
    "data1": {
      "keep": "true"
    }
  },
  "detail": {
    "data2": [
      {
        "keep1": "keep1value",
        "keep2": "keep2value"
      }
    ],
    "data3": [
      {
        "keep1": "keep1value",
        "keep2": "keep2value"
      }
    ]
  }
}

反过来,你可以使用paths(scalars)列出所有的叶子路径,过滤掉那些最底层的.[-1]not不匹配的路径,然后使用delpaths删除剩下的叶子路径:

delpaths([paths(scalars) | select(
  .[-1] | IN("keep", "keep1", "keep2") | not
)])

Demo

相关问题