如何使用jq合并2 json文件?

时间:2013-10-22 22:43:47

标签: json shell command-line jq

我在shell脚本中使用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"
        }
    }
}

file2的

{
    "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

6 个答案:

答案 0 :(得分:104)

从1.4开始,现在可以使用*运算符。给定两个对象时,它将以递归方式合并它们。例如,

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

会得到你:

{
  "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

答案 1 :(得分:42)

使用jq -s add

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

这会将stdin中的所有JSON文本读入数组(jq -s执行此操作),然后它会减少"它们。

add定义为def add: reduce .[] as $x (null; . + $x);,它迭代输入数组的对象值并添加它们。对象添加==合并。)

答案 2 :(得分:27)

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

一旦进入--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

(注意:如果你想合并内部对象而不是只用正确的文件覆盖左边的文件,你需要手动完成)

答案 3 :(得分:15)

这是一个在任意数量的对象上以递归方式(使用echo '{"A": {"a": 1}}' '{"A": {"b": 2}}' '{"B": 3}' | jq --slurp 'reduce .[] as $item ({}; . * $item)' { "A": { "a": 1, "b": 2 }, "B": 3 } )运行的版本:

jQuery('#multiselect').val("");

答案 4 :(得分:5)

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

其次,--argfile选项(在jq 1.4和jq 1.5中可用)可能是有意义的,因为它避免了必须使用--slurp选项。

将这两个文件组合在一起,可以按照以下指定的方式组合:

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

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

答案 5 :(得分:0)

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

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

或针对任意数量的文件

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