jq:将对象数组转换为对象

时间:2018-04-21 16:47:10

标签: json bash translation jq

我收到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的方式)。

我已经在这工作了一段时间,而且每次我得到一个deadend。

注意:如果需要,我可以使用Shell等预先形成循环。

编辑:这是我迄今为止开发的一个版本:

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

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

3 个答案:

答案 0 :(得分:2)

[编辑:以下回答是在回答问题时描述(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) )

答案 1 :(得分:1)

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

.[].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
    }
  }
]

答案 2 :(得分:0)

这是针对修订问题的无减少解决方案。

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

def mapping:
{
  "12": "newId1",
  "13": "newId2",
  "14": "newId3"
} ;


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

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