仅在子级别上应用 jq 过滤器,保持 JSON 的其余部分完好无损

Posted

技术标签:

【中文标题】仅在子级别上应用 jq 过滤器,保持 JSON 的其余部分完好无损【英文标题】:apply jq filter on sub level only, keeping the rest of the JSON intact 【发布时间】:2020-03-13 19:38:47 【问题描述】:

给定一个嵌套对象,是否可以只对 json 的子级别应用过滤器,然后将包含应用过滤器的子级别的原始 json 作为输出?

例如,如果我有这样的 json:

"k1": "v1",
 "k2": "v2",
 "k3": "v3",
 "k4": [],
 "records": [
        "kk1": "vv1",
        "kk2": ["vv2"],
        "releases": ["kkk1":"vvv1", 
                     "parties":["name":"value",
                                  "kkkk1":"value", 
                                 "name":"value",
                                  "kkkk1":"value"]],
        "kk4": "vv4",

        "kk5": "vv5",
        
        "kk1": "o_vv1",
        "kk2": ["o_vv2"],
        "releases": ["kkk1":"o_vvv1", 
                     "parties":["name":"o_value",
                                  "kkkk1":"o_value", 
                                "name":"o_value",
                                 "kkkk1":"o_value"]],
        "kk4": "o_vv4",

        "kk5": "o_vv5"],
 "k6":"v6"

我希望输出同样的 json,但将 .[].records[].releases[].parties 中的嵌套对象展平,因此所需的输出应该是:

previous keys
...
 "records": [
        "kk1": "vv1",
        "kk2": ["vv2"],
        "releases": ["kkk1":"vvv1", 
                     "parties.0.name":"value",
                      "parties.0.kkkk1":"value", 
                      "parties.1.name":"value",
                      "parties.1.kkkk1": "value"]
       "kk4": "vv4",
       "kk5": "vv5", 
       
       "kk1": "other_vv1",
       "kk2": ["other_vv2"],
       "releases": ["kkk1":"vvv1", 
                    "parties.0.name":"value",
                     "parties.0.kkkk1":"value", 
                     "parties.1.name":"value",
                     "parties.1.kkkk1": "value"]
       "kk4": "other_vv4",
       "kk5": "other_vv5",
...
following keys

编辑: 当前 jq 命令:

 jq '.[].records[].releases[].parties| . as $ho | reduce paths(scalars) as $path (; . + ($path | map(tostring) | join(".")): $ho | getpath($path))'

【问题讨论】:

您的示例输入与您发布的实际数据不匹配;您的示例的有效解决方案可能不适用于您的实际输入,反之亦然。请修复它并告诉我们,另见minimal reproducible example 【参考方案1】:

如果你只想替换一个子部分,你可以使用 |= 而不是 | ,就在 .parties 之后

所以我认为这将实现您的目标:

.[].records[].releases[].parties |= 
  (. as $ho 
   | reduce paths(scalars) as $path (;
       . + ($path | map(tostring) | join(".")):
             $ho | getpath($path)))

【讨论】:

以上是关于仅在子级别上应用 jq 过滤器,保持 JSON 的其余部分完好无损的主要内容,如果未能解决你的问题,请参考以下文章

仅在子例程中需要时才使用 Perl 模块

jq 以 JSON 格式输出结果

仅在内容类型 === JSON 时更改 Java 过滤器中的内容类型或字符编码

jq处理JSON数据

jq 过滤内部数组元素但返回整个 JSON

Sharepoint 2010列表视图阈值和项级别权限