【问题标题】:jq - apply a filter on multiple levelsjq - 在多个级别上应用过滤器
【发布时间】:2015-05-13 10:36:17
【问题描述】:

我有一个这样的 json 文件

{
    "log": {
            "version": {
                    "$t": "1.1"
            },
            "creator": {
                    "name": {
                            "$t": "Internet Explorer Network Inspector"
                    },
                    "version": {
                            "$t": "10.0.9200.17229"
                    }
            }
}

我需要将文件展平,以便它可以读取

{
    "log": {
            "version": "1.1",
            "creator": {
                    "name": "Internet Explorer Network Inspector",
                    "version": "10.0.9200.17229"
            }
}

我知道过滤器 {"version": .version ."$t"} 将单个元素 "version": {"$t": "10.0.9200.17229"} 减少到 {"version": "10.0.9200.17229"},但是这个过滤器应该递归地应用于任何级别的任何元素。

【问题讨论】:

    标签: json recursion jq flatten


    【解决方案1】:

    您可以通过定义新函数来创建递归过滤器:

    def untag: (objects | ."$t")
        // (objects | with_entries(.value |= untag))
        // (arrays | map(untag))
        // .
        ;
    untag
    

    所以给定这样的输入:

    {
      "log": {
        "version": {
          "$t": "1.1"
        },
        "creator": {
          "name": {
            "$t": "Internet Explorer Network Inspector"
          },
          "version": {
            "$t": "10.0.9200.17229"
          }
        }
      }
    }
    

    你会回来的:

    {
      "log": {
        "creator": {
          "name": "Internet Explorer Network Inspector",
          "version": "10.0.9200.17229"
        },
        "version": "1.1"
      }
    }
    

    【讨论】:

    • 所以解释一下。我们定义了一个函数untag,它选择作为对象的输入,如果它们有$t,则提取值否则使用来自untag的值更新对象的值(这是递归部分)。最后,如果我们没有任何$t,该函数将返回输入本身。
    • 如果你有数组,我已经添加了一些来处理数组。并且不需要对 $t 属性的初始检查。我以为它会抛出一个错误,但它不会。
    • 谢谢杰夫,我正在编辑答案以添加数组处理。希望我注意到 stackoverflow 顶部栏上的红色警报;-) 这样做的原因是将 IE 中的 NetworkData.xml 转换为 HAR 格式。我发现xml2json 的第一个 XML > JSON 工具非常冗长,因此我需要将结果展平。确实还有一步,将pageentries中的对象转换为普通数组,但这应该很简单......
    • untag 函数放在哪里?它是如何从命令行调用的?我正在尝试使用 some_command | xml2json | jquntag 进行类似的操作。
    • @jwfearn 只需调用它。 ... | jq 'untag'
    【解决方案2】:

    如果你的jq有walk,你可以如下使用它,如果没有,你可以很容易地google它的def并通过剪切和粘贴的方式包含它:

    walk( if type=="object" and has("$t")
          then .["$t"] else . end )
    

    【讨论】:

      【解决方案3】:

      扩展 @JeffMercado 的出色回答:

      问题

      您有一些生成 JSON 的命令,其中字符串值表示如下

      {"some key": {"$t": "some string value"}}
      

      并且您希望将其转换为如下所示:

      {"some key": "some string value"}
      

      解决方案

      把它放在你的~/.jq 文件中:

      def untag: (objects | ."$t")
        // (objects | with_entries(.value |= untag))
        // (arrays | map(untag))
        // .
        ;
      

      像这样使用它:

      some_command | jq untag
      

      例子:

      $ echo '{"some key": {"$t": "some string value"}}' | jq
      {
        "some key": {
          "$t": "some string value"
        }
      }
      
      $ echo '{"some key": {"$t": "some string value"}}' | jq untag
      {
        "some key": "some string value"
      }
      

      【讨论】:

        猜你喜欢
        • 2015-08-26
        • 2015-08-05
        • 2015-09-11
        • 2020-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多