考虑文件“ b.json”:
[
{
"id": 3,
"foo": "cannot be replaced, id isn't in a.json, stay untouched",
"baz": "do not touch3"
},
{
"id": 2,
"foo": "should be replaced with 'foo new2'",
"baz": "do not touch2"
}
]
和'a.json':
[
{
"id": 2,
"foo": "foo new2",
"baz": "don't care"
}
]
我想使用jq和来自a.json的匹配值来更新b.json中的键“ foo”。它也应该与a.json中的多个条目一起使用。
因此所需的输出是:
[
{
"id": 3,
"foo": "cannot be replaced, id isn't in a.json, stay untouched",
"baz": "do not touch3"
},
{
"id": 2,
"foo": "foo new2",
"baz": "do not touch2"
}
]
答案 0 :(得分:1)
这是使用INDEX/2
的几种可能性之一。如果您的jq没有内置此功能,请参见下文。
jq --argfile a a.json '
INDEX($a[]; .id) as $dict
| map( (.id|tostring) as $id
| if ($dict|has($id)) then .foo = $dict[$id].foo
else . end)' b.json
还有其他方法可以传递a.json和b.json的内容。
上面对INDEX的使用假定不存在“冲突”,例如,如果一个对象的.id等于1,而另一个对象的.id等于“ 1”,则会发生这种情况。如果可能发生这种冲突,则可以使用更复杂的INDEX定义。
INDEX/2
直接从Builtin.jq:
def INDEX(stream; idx_expr):
reduce stream as $row ({}; .[$row|idx_expr|tostring] = $row);
答案 1 :(得分:1)
这是一个通用答案,除了它们是不同的JSON值之外,没有对.id密钥的值进行任何假设。
def type2: [type, if type == "string" then . else tojson end];
def dictionary(stream; f):
reduce stream as $s ({}; setpath($s|f|type2; $s));
def lookup(value):
getpath(value|type2);
def indictionary(value):
(value|type2) as $t
| has($t[0]) and (.[$t[0]] | has($t[1]));
jq --argfile a a.json -f program.jq b.json
dictionary($a[]; .id) as $dict
| b
| map( .id as $id
| if ($dict|indictionary($id))
then .foo = ($dict|lookup($id).foo)
else . end)