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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19529688/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 19:56:51  来源:igfitidea点击:

How to merge 2 JSON objects from 2 files using jq?

jsonshellcommand-linejq

提问by Janfy

I'm using the jqtools (jq-json-processor) in shell script to parse json.

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

I've got 2 json files and want to merge them into one unique file

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

Here the content of files:

这里是文件的内容:

file1

文件 1

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

file2

文件 2

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

expected result

预期结果

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

I try a lot of combinaison but the only result i get is the following, which is not the expected result:

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

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

Using this command:

使用这个命令:

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

回答by Simo Kinnunen

Since 1.4 this is now possible with the *operator. When given two objects, it will merge them recursively. For example,

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

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

Important: Note the -s (--slurp)flag, which puts files in the same array.

重要提示:请注意-s (--slurp)将文件放在同一个数组中的标志。

Would get you:

会让你:

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

If you also want to get rid of the other keys (like your expected result), one way to do it is this:

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

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

Or the presumably somewhat more efficient (because it doesn't merge any other values):

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

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

回答by user2259432

Use jq -s add:

使用jq -s add

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

This reads all JSON texts from stdin into an array (jq -sdoes that) then it "reduces" them.

jq -s会将所有 JSON 文本从 stdin 读取到一个数组中(这样做)然后“减少”它们。

(addis defined as def add: reduce .[] as $x (null; . + $x);, which iterates over the input array's/object's values and adds them. Object addition == merge.)

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

回答by FiloSottile

Who knows if you still need it, but here is the solution.

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

Once you get to the --slurpoption, it's easy!

一旦找到--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.

Then the +operator will do what you want:

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

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

(Note: if you want to merge inner objects instead of just overwriting the left file ones with the right file ones, you will need to do it manually)

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

回答by jrib

Here's a version that works recursively (using *) on an arbitrary number of objects:

这是一个*在任意数量的对象上递归(使用)的版本:

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

回答by peak

First, {"value": .value} can be abbreviated to just {value}.

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

Second, the --argfile option (available in jq 1.4 and jq 1.5) may be of interest as it avoids having to use the --slurp option.

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

Putting these together, the two objects in the two files can be combined in the specified way as follows:

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

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

The '-n' flag tells jq not to read from stdin, since inputs are coming from the --argfile options here.

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

回答by dngray

This can be used to merge any number of files specified on the command:

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

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

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

or this for any number of files

或者这适用于任意数量的文件

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

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