合并两个复杂的JSON对象(使用jq)

时间:2017-05-19 14:07:42

标签: json object merge jq

我正在尝试替换复杂JSON对象中的对象。似乎工具jq可以提供完美的解决方案,但我真的在努力选择正确的过滤器/链条。

我有一个完整的配置JSON对象,看起来像这样(有更多的键,缩短了它的插图):

{
    "some-array": [
        {
            "name": "foo",
            "attr": "value"
        },
        {
            "name": "foo bar",
            "attr": "value"
        },
        {
            "name": "foo bar baz",
            "attr": "value"
        }
    ],
    "some-other-array": []
}

现在我有另一个包含带有更新对象的数组的对象,我需要以某种方式与完整配置合并。我需要按名称查找嵌套对象,如果它还不存在则添加它,如果它存在则替换它。

{
    "some-array": [
        {
            "name": "foo",
            "attr": "new-value",
            "new-attrib": "new-value"
        },
        {
            "name": "foo bar",
            "attr": "new-value"
        }
    ]
}

因此,通过上面的例子,我的预期结果将是:

{
    "some-array": [
        {
            "name": "foo",
            "attr": "new-value",
            "new-attrib": "new-value"
        },
        {
            "name": "foo bar",
            "attr": "new-value"
        },
        {
            "name": "foo bar baz",
            "attr": "value"
        }
    ],
    "some-other-array": []
}

我已经尝试select(."some-array"[].name == "foo")作为jq过滤器开始使用其他一些东西,但我很难在这里继续前进,并且非常感谢一些灵感/实际的解决方案。

任何人都可以告诉我,我想要实现的目标是jq实际可行,还是我必须找到另一种解决方案?

2 个答案:

答案 0 :(得分:1)

是的,这是可能的,事实上,在最初陈述的问题的各种解释下很容易。

以下解决了最初陈述的问题,“它”被解释为.["some-array"]而不是其成分。

假设$update持有包含所显示更新信息的对象,则可以使用此过滤器执行更新:

.["some-array"] = ($update | .["some-array"])

有许多方法可以赋予$update所需的值。

答案 1 :(得分:1)

以下是更新问题的解决方案。此解决方案假定名称是字符串值。它依赖于两个辅助函数:

# array-to-hash
def a2h(f): reduce .[] as $x ({}; . + {($x | f): $x});

# hash-to-array
def h2a: . as $in | reduce keys_unsorted[] as $k ([]; . + [$in[$k]]);

第一个创建了#34;哈希"基于输入数组,第二个实现逆操作。

使用这些辅助函数,可以编写解决方案:

.["some-array"] |= (a2h(.name) + ($update|.["some-array"] | a2h(.name)) | h2a)

其中$update是"新"值。这个解决方案依赖于"右支配"对象添加。

输出

对于给定的示例,输出为:

{
  "some-array": [
    {
      "name": "foo",
      "attr": "new-value",
      "new-attrib": "new-value"
    },
    {
      "name": "foo bar",
      "attr": "new-value"
    },
    {
      "name": "foo bar baz",
      "attr": "value"
    }
  ],
  "some-other-array": []
}