JQ:按照索引/对应顺序将单个JSON对象添加到另一个JSON对象中

lhcgjxsq  于 2023-05-30  发布在  其他
关注(0)|答案(2)|浏览(128)

我有两个简单的JSON对象,我试图从一个Bash变量newValArr中添加一个对象,按照相应对象的顺序添加到masterfile.json中。它们如下所示:
newValArr

[{ "firstValue": "foo", "secondValue": "bar"},
 { "firstValue": "baz", "secondValue": "qux"},
 ...
]

masterfile.json

{
  "value": [
    {
      "id": "abc",
      "properties": {
        "blah": "stuff"
      }
    },
    {
      "id": "def",
      "properties": {
        "blah": "morestuff"
      }
    },
...
  ]
}

我在Bash中创建了以下脚本,将firstValuesecondValue对象添加到value对象数组中的预期位置,以下是脚本:

jq --argjson newvalues "${newValArr}" '.value[].properties.newObject += $newvalues[0]' masterfile.json > newoutput.json

下面是当前的JSON输出:
newoutput.json

{
  "value": [
    {
      "id": "abc",
      "properties": {
        "blah": "stuff",
        "newObject": {
          "firstValue": "foo", 
          "secondValue": "bar"
        }
      }
    },
    {
      "id": "def",
      "properties": {
        "blah": "otherstuff",
        "newObject": {
          "firstValue": "foo", 
          "secondValue": "bar"
        }
      }
    },
...
  ]
}

所需输出为:

{
  "value": [
    {
      "id": "abc",
      "properties": {
        "blah": "stuff",
        "newObject": {
          "firstValue": "foo", 
          "secondValue": "bar"
        }
      }
    },
    {
      "id": "def",
      "properties": {
        "blah": "otherstuff",
        "newObject": {
          "firstValue": "baz", 
          "secondValue": "qux"
        }
      }
    },
...
  ]
}

很明显,问题是相同的newValArr对象被放置到每个newObject中,因为我们不断地引用相同的索引。如果我们不指定索引,那么所有的newValArr对象将被放置到每个newObject中,我不太确定是否可以像在Bash中使用newValArr[@]那样迭代JQ中的索引,以便每个索引都可以按顺序分配。在JQ可以吗?还是必须使用完全不同的方法?
这两个JSON将始终具有相同数量的对象,以相同的顺序,无需担心这一点。
我已经研究过使用to_entires实现这个,但是它似乎与我试图实现的目标不兼容。

8ehkhllq

8ehkhllq1#

您可以使用to_entries,当应用于数组时,在.key字段中生成索引,然后可以使用该索引来索引导入的变量。然后,只需对结果数组执行map操作即可构造最终对象。

jq --argjson vals "$newValArr" '.value |= (to_entries | map(
  $vals[.key] as $newObject | .value | .properties += {$newObject}
))' masterfile.json
{
  "value": [
    {
      "id": "abc",
      "properties": {
        "blah": "stuff",
        "newObject": {
          "firstValue": "foo",
          "secondValue": "bar"
        }
      }
    },
    {
      "id": "def",
      "properties": {
        "blah": "morestuff",
        "newObject": {
          "firstValue": "baz",
          "secondValue": "qux"
        }
      }
    }
  ]
}
soat7uwm

soat7uwm2#

一种方法是创建数组的所有索引的范围,并通过组合相应的元素来构建一个新对象:

#!/usr/bin/env bash

newValArr='
[{ "firstValue": "foo", "secondValue": "bar"},
 { "firstValue": "baz", "secondValue": "qux"}
]
'

jq -n --argjson newval "$newValArr" --argfile master masterfile.json '
   { value: [ range($master.value | length)
              | . as $n
              | $master.value[$n] * { properties: { newObject: $newval[$n] } }
            ]
   }'

产出

{
  "value": [
    {
      "id": "abc",
      "properties": {
        "blah": "stuff",
        "newObject": {
          "firstValue": "foo",
          "secondValue": "bar"
        }
      }
    },
    {
      "id": "def",
      "properties": {
        "blah": "morestuff",
        "newObject": {
          "firstValue": "baz",
          "secondValue": "qux"
        }
      }
    }
  ]
}

或者使用transposezip the two arrays的另一种方法,然后将它们合并:

jq --argjson newval "$newValArr" '
   .value |= [ [ ., $newval ] | transpose[] | .[0] * { properties: { newObject: .[1] }} ]
' masterfile.json

相关问题