【问题标题】:jq: translate array of objects to objectjq:将对象数组转换为对象
【发布时间】:2018-05-05 12:34:37
【问题描述】:

我收到 curl 的回复,格式如下:

[
  {
    "list": [
      {
        "value": 1,
        "id": 12
      },
      {
        "value": 15,
        "id": 13
      },
      {
        "value": -4,
        "id": 14
      }
    ]
  },
  ...
]

给定 id 之间的映射如下:

{
  "12": "newId1",
  "13": "newId2",
  "14": "newId3"
}

我想做这个:

[
  {
    "list": {
      "newId1": 1,
      "newId2": 15,
      "newId3": -4,
    }
  },
  ...
]

这样我就得到了从 id 到值的映射(并且在此过程中我想重新映射 id)。

我已经为此工作了一段时间,每次遇到死胡同。

注意:如有必要,我可以使用 Shell 或类似工具来执行循环。

编辑:这是我目前开发的一个版本:

jq '[].list.id = ($mapping.[] | select(.id == key)) | del(.id)' -M --argjson "mapping" "$mapping"

我认为这不是最好的,但我正在寻找是否能找到更接近我需要的旧版本。

【问题讨论】:

    标签: json bash translation jq


    【解决方案1】:

    [编辑:以下响应是对问题的回答,它描述了(a)如下所示的映射,以及(b)输入数据具有以下形式:

    [
      {
        "list": [
          {
            "value": 1,
            "id1": 12
          },
          {
            "value": 15,
            "id2": 13
          },
          {
            "value": -4,
            "id3": 14
          }
        ]
      }
    ]
    

    编辑结束]

    在下文中,我将假设映射可通过以下函数获得,但这是一个无关紧要的假设:

    def mapping: {
      "id1": "newId1",
      "id2": "newId2",
      "id3": "newId3"
    } ;
    

    下面的 jq 过滤器将产生所需的输出:

    map( .list
         |= (map( to_entries[]
                  | (mapping[.key]) as $mapped
                  | select($mapped)
                  | {($mapped|tostring): .value} )
             | add) )
    

    【讨论】:

    • 在第 3 行,.key 不是 = 0、1 还是 2?那不总是映射变量中未定义的索引吗?
    • 没关系。我让它工作了!非常感谢,我已经为此苦苦挣扎了好几个小时了。
    • @user2752635 - 有人更改了问题,所以我添加了单独的回复。
    【解决方案2】:

    有很多方法可以给猫剥皮。我会这样做:

    .[].list |= reduce .[] as $i ({};
        ($i.id|tostring) as $k
          | (select($mapping | has($k))[$mapping[$k]] = $i.value) // .
    )
    

    您只需通过单独的文件或参数提供映射。

    $ cat program.jq
    .[].list |= reduce .[] as $i ({};
        ($i.id|tostring) as $k
          | (select($mapping | has($k))[$mapping[$k]] = $i.value) // .
    )
    
    $ cat mapping.json
    {
      "12": "newId1",
      "13": "newId2",
      "14": "newId3"
    }
    
    $ jq --argfile mapping mapping.json -f program.jq input.json
    [
      {
        "list": {
          "newId1": 1,
          "newId2": 15,
          "newId3": -4
        }
      }
    ]
    

    【讨论】:

      【解决方案3】:

      这里是修改后的问题的一个无减少的解决方案。

      在下文中,我将假设映射可通过以下函数获得,但这是一个无关紧要的假设:

      def mapping:
      {
        "12": "newId1",
        "13": "newId2",
        "14": "newId3"
      } ;
      
      
      map( .list
           |= (map( mapping[.id|tostring] as $mapped
                    | select($mapped)
                    |  {($mapped): .value} )
               | add) )
      

      “选择”是为了安全(即,它检查所考虑的 .id 是否确实已映射)。通过编写{($mapped|tostring): .value} 来确保$mapped 是一个字符串也可能是合适的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-07
        • 2023-01-24
        • 1970-01-01
        • 2020-06-15
        • 2016-03-11
        • 2018-05-13
        相关资源
        最近更新 更多