我在shell脚本中使用jq工具(jq-json-processor)解析json。

我有2个json文件,想合并成一个独特的文件

这里是文件的内容:

file1

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

当前回答

使用jq -s add:

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

这将把所有JSON文本从stdin读入一个数组(jq -s就是这样做的),然后它“减少”它们。

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

其他回答

使用jq -s add:

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

这将把所有JSON文本从stdin读入一个数组(jq -s就是这样做的),然后它“减少”它们。

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

从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

谁知道你是否还需要它,但这里有一个解决方案。

一旦你选择了“啜”这个选项,就很简单了!

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

(注意:如果你想合并内部对象,而不是用右边的文件覆盖左边的文件,你需要手动操作)

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

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

或者对于任意数量的文件

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

下面是递归工作的版本(使用*)任意数量的对象:

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

{
  "A": {
    "a": 1,
    "b": 2
  },
  "B": 3
}