更新时间:2023-01-08 12:15:38
Here is a solution which uses Object Multiplication. Assuming your data is in A.json
and B.json
:
$ jq -M --argfile b B.json '.[0].elements[0] *= $b[0].elements[0]' A.json
产生
[
{
"uri": "https://someurl.com",
"id": "some-id",
"keyword": "SomeKeyword",
"name": "Some Name",
"description": "Some description for that test result",
"line": 2,
"tags": [
{
"name": "@sometag",
"line": 1
}
],
"elements": [
{
"a": 5,
"b": 2
}
]
}
]
如果您的数组包含更多数据,则很容易推广这种方法,但是您需要了解如何识别相应的元素.
This approach is easily generalized if your arrays contain more data but you'll need to understand how corresponding elements should be identified.
关于修订后的问题,这是一个过滤器,该过滤器用具有相同 .id的
B.json
的相应对象更新 A.json
的对象.代码>:
Regarding the revised question, here is a filter which updates objects of A.json
with corresponding objects of B.json
having the same .id
:
def INDEX(stream; idx_expr):
reduce stream as $row ({};
.[$row|idx_expr| if type != "string" then tojson else . end] |= $row);
def merge_by_id(a;b):
if b then INDEX(a[];.id) * INDEX(b[];.id) | map(.) else a end;
INDEX($b[];.id) as $i
| map( .elements = merge_by_id(.elements; $i[.id].elements) )
例如,如果上述过滤器位于 filter.jq
中,则 A.json
包含修订后的示例数据,而 B.json
包含
For example if the above filter is in filter.jq
, A.json
contains the revised sample data and B.json
contains
[
{
"id": "safety-tests",
"elements": [
{
"id": "some-element-id",
"description": "updated description"
}
]
}
]
命令
$ jq -M --argfile b B.json -f filter.jq A.json
生成结果
[
{
"uri": "some/url.feature",
"id": "safety-tests", <------ top level .id
...
"elements": [
{
"id": "some-element-id", <------ element .id
"keyword": "Scenario Outline",
"name": ": Some scenario name",
"description": "updated description", <------ updated value
"line": 46,
"type": "scenario",
...
请注意,上述解决方案假定 A.json
中元素的 .id
是唯一的,否则 merge_by_id
不会产生所需的输出.在这种情况下,以下过滤器就足够了:
Note that the above solution assumes the .id
of the elements in A.json
are unique otherwise merge_by_id
won't produce the desired output. In that case the following filter should suffice:
def INDEX(stream; idx_expr):
reduce stream as $row ({};
.[$row|idx_expr| if type != "string" then tojson else . end] |= $row);
(INDEX($b[];.id) | map_values(INDEX(.elements[];.id))) as $i
| map( $i[.id] as $o | if $o then .elements |= map($o[.id]//.) else . end )
此过滤器仅要求 B.json
中的对象的 .id
是唯一的.如果 A.json
和 B.json
中都可能存在非唯一元素,则需要更复杂的映射.
This filter only requires the .id
of the objects in B.json
to be unique. If it's possible for there to be non-unique elements in both A.json
and B.json
then a more sophisticated mapping then this one will be required.
以下是带有注释的过滤器版本:
Here is a version of the filter with comments:
def INDEX(stream; idx_expr):
reduce stream as $row ({};
.[$row|idx_expr| if type != "string" then tojson else . end] |= $row);
# first create a lookup table for elements from B.json
( # [{id:x, elements:[{id:y, ...}]}]
INDEX($b[];.id) # -> {x: {id:x, elements:[{id:y, ...}]}..}
| map_values(INDEX(.elements[];.id)) # -> {x: {y: {id:y, ...}}}
) as $i
# update A.json objects
| map( # for each object in A.json
$i[.id] as $o # do we have updated values from B.json ?
| if $o then .elements |= map($o[.id]//.) # if so then replace corresponding elements
else . end # otherwise leave object unchanged
)