jq:递归合并对象并连接数组 [英] jq: recursively merge objects and concatenate arrays

查看:258
本文介绍了jq:递归合并对象并连接数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个json文件,分别为orig.json和patch.json,它们的格式相似.

I have two json files, orig.json and patch.json, which have similar formats.

orig.json:

orig.json:

{
        "a": {
                "a1": "original a1",
                "a2": "original a2",
                "list": ["baz", "bar"]
        },
        "b": "original value B"
}

patch.json:

patch.json:

{
    "a": {
            "a1": "patch a1",
            "list": ["foo"]
    },
    "c": "original c"
}

当前,我正在使用jq递归合并它们.但是,jq的列表默认行为只是重新分配.使用$ jq -s '.[0] * .[1]' orig.json patch.json:

Currently I am using jq to merge them recursively. However, jq's default behavior for lists is just reassignment. Example output from jq using $ jq -s '.[0] * .[1]' orig.json patch.json:

{
  "a": {
    "a1": "patch a1",
    "a2": "original a2",
    "list": [
      "foo"
    ]
  },
  "b": "original value B",
  "c": "original c"
}

请注意,a.list现在等于patch.json的a.list.我希望新的a.list被orig.json的列表和patch.json的列表合并.换句话说,我希望a.list等于["baz", "bar", "foo"].

Note that a.list is now equal to patch.json's a.list. I want The new a.list to be orig.json's list and patch.json's lists merged. In other words, I want a.list to equal ["baz", "bar", "foo"].

有没有一种方法可以通过jq轻松地做到这一点,也许可以通过重写数组的默认合并策略来实现?

Is there a way I can easily do this with jq, perhaps by overriding the default merge strategy for arrays?

推荐答案

这是一个通用函数,该函数通过在同一位置串联数组来递归组合两个复合JSON实体:

Here is a generic function that recursively combines two composite JSON entities by concatenating arrays at the same position:

# Recursively meld a and b,
# concatenating arrays and
# favoring b when there is a conflict 
def meld(a; b):
  if (a|type) == "object" and (b|type) == "object"
  then reduce ([a,b]|add|keys_unsorted[]) as $k ({}; 
    .[$k] = meld( a[$k]; b[$k]) )
  elif (a|type) == "array" and (b|type) == "array"
  then a+b
  elif b == null then a
  else b
  end;

meld($ orig; $ patch)的输出

将$ orig设置为orig.json的内容,然后 $ patch设置为patch.json的内容:

Output of meld($orig; $patch)

With $orig set to the contents of orig.json and $patch set to the contents of patch.json:

{
  "a": {
    "a1": "patch a1",
    "a2": "original a2",
    "list": [
      "baz",
      "bar",
      "foo"
    ]
  },
  "b": "original value B",
  "c": "original c"
}

这篇关于jq:递归合并对象并连接数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆