如何使用jq从2个文件合并2个JSON对象?


123

我在外壳程序脚本中使用jq工具(jq-json-processor)来解析json。

我有2个json文件,想将它们合并为一个唯一的文件

这里是文件的内容:

文件1

{
    "value1": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2"
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        }
    }
}

文件2

{
    "status": 200,
    "timestamp": 1382461861,
    "value": {
        "aaa": {
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value3": "v3"
        },      
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

预期结果

{
    "value": {
        "aaa": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3",
            "value4": 4
        },
        "bbb": {
            "value1": "v1",
            "value2": "v2",
            "value3": "v3"
        },
        "ccc": {
            "value1": "v1",
            "value2": "v2"
        },
        "ddd": {
            "value3": "v3",
            "value4": 4
        }
    }
}

我尝试了很多组合,但是得到的唯一结果是以下结果,这不是预期的结果:

{
  "ccc": {
    "value2": "v2",
    "value1": "v1"
  },
  "bbb": {
    "value2": "v2",
    "value1": "v1"
  },
  "aaa": {
    "value2": "v2",
    "value1": "v1"
  }
}
{
  "ddd": {
    "value4": 4,
    "value3": "v3"
  },
  "bbb": {
    "value3": "v3"
  },
  "aaa": {
    "value4": 4,
    "value3": "v3"
  }
}

使用此命令:

jq -s '.[].value' file1 file2

1
您尝试过jsontool吗?github.com/trentm/json
Nano Taboada

还没有,我来看一下。Thx
Janfy

json使用此功能,请执行以下操作:cat f1 f2 | json --deep-merge
xer0x 2014年

您在哪里/如何获得json@ xer0x?
古斯

@Gus哦,要获得该json工具,请访问github.com/trentm/json
xer0x

Answers:


154

从1.4开始,*操作员现在可以做到这一点。当给定两个对象时,它将递归合并它们。例如,

jq -s '.[0] * .[1]' file1 file2

重要提示:请注意 -s (--slurp)标志,它将文件放置在同一阵列中。

会给你:

{
  "value1": 200,
  "timestamp": 1382461861,
  "value": {
    "aaa": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3",
      "value4": 4
    },
    "bbb": {
      "value1": "v1",
      "value2": "v2",
      "value3": "v3"
    },
    "ccc": {
      "value1": "v1",
      "value2": "v2"
    },
    "ddd": {
      "value3": "v3",
      "value4": 4
    }
  },
  "status": 200
}

如果您还想摆脱其他键(如您的预期结果),一种方法是:

jq -s '.[0] * .[1] | {value: .value}' file1 file2

或者大概更有效(因为它没有合并任何其他值):

jq -s '.[0].value * .[1].value | {value: .}' file1 file2

2
注意:该-s标志很重要,因为没有它,两个对象就不在数组中。
约翰·莫拉莱斯

1
@SimoKinnunen在这里,我们正在合并两个json文件。是否有可能有1个json变量和其他json文件。我尝试过,但似乎对我不起作用!
Jayesh Dhandha '18

如果单个文件按键排序,是否可以在生成的文件中保留顺序?
狮子座

@SimoKinnunen我正在使用以下命令:“ jq -s'add'config.json other / *。json”,但是当我执行“ cat config.json”时,它不会合并。如何将输出放回文件?
Renato Bibiano

63

用途jq -s add

$ echo '{"a":"foo","b":"bar"} {"c":"baz","a":0}' | jq -s add
{
  "a": 0,
  "b": "bar",
  "c": "baz"
}

这会将所有JSON文本从标准输入读入数组(jq -s这样做),然后“减少”它们。

add定义为def add: reduce .[] as $x (null; . + $x);,它会迭代输入数组/对象的值并将其相加。对象加法== merge。)


4
是否可以使用这种方法进行递归合并(*运算符)?
Dave Foster 2014年

1
@DaveFoster是的,类似reduce .[] as $x ({}; . * $x)-参见jrib的答案
Chriki

这帮助我使用Ansible和jq合并了两个json文件。谢谢。
费利佩·阿尔瓦雷斯

35

谁知道您是否仍然需要它,但这是解决方案。

一旦获得--slurp选择,这很容易!

--slurp/-s:
    Instead of running the filter for each JSON object in the input,
    read the entire input stream into a large array and run the filter just once.

然后,+操作员将执行您想要的操作:

jq -s '.[0] + .[1]' config.json config-user.json

(注意:如果要合并内部对象,而不是仅用正确的文件覆盖左文件的对象,则需要手动进行操作)


19

这是一个可*在任意数量的对象上递归工作的版本:

echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --slurp 'reduce .[] as $item ({}; . * $item)'
{
  "A": {
    "a": 1,
    "b": 2
  },
  "B": 3
}

2
好答案。合并目录中的所有文件时,效果很好:jq -s 'reduce .[] as $item ({}; . * $item)' *.json
John Ellmore

7

首先,{“ value”:.value}可以缩写为{value}。

其次,--argfile选项(在jq 1.4和jq 1.5中可用)可能会引起关注,因为它避免了使用--slurp选项。

将它们放在一起,可以按以下指定方式组合两个文件中的两个对象:

$ jq -n --argfile o1 file1 --argfile o2 file2 '$o1 * $o2 | {value}'

因为输入来自--argfile选项,所以-n标志告诉jq不要从stdin读取。


2
JQ已经过时--argile--slurpfile
大卫Groomes

3

这可以用于合并命令上指定的任意数量的文件:

jq -rs 'reduce .[] as $item ({}; . * $item)' file1.json file2.json file3.json ... file10.json

或任意数量的文件

jq -rs 'reduce .[] as $item ({}; . * $item)' ./*.json

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.