使用 JQ 合并两个嵌套的 JSON 文件
Merge two nested JSON files using JQ
我正在尝试合并两个 JSON 文件。主要目标是用第二个文件中的 environment
个变量覆盖第一个文件中的 environment
个变量。
第一个文件:
{
"containerDefinitions": [
{
"name": "foo",
"image": "nginx:latest",
"cpu": 1024,
"memory": 4096,
"memoryReservation": 2048,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 0,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "SERVER_PORT",
"value": "8080"
},
{
"name": "DB_NAME",
"value": "example_db"
}
],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/dev/ecs/example",
"awslogs-region": "us-west-1",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"family": "bar",
"taskRoleArn": "arn:aws:iam::111111111111:role/assume-ecs-role",
"executionRoleArn": "arn:aws:iam::111111111111:role/ecs-task-execution-role",
"networkMode": "bridge",
"volumes": [],
"placementConstraints": [],
"requiresCompatibilities": [
"EC2"
]
}
第二个文件:
{
"containerDefinitions": [
{
"environment": [
{
"name": "SERVER_PORT",
"value": "8081"
}
]
}
]
}
下一个产品必须是:
{
"containerDefinitions": [
{
"name": "foo",
"image": "nginx:latest",
"cpu": 1024,
"memory": 4096,
"memoryReservation": 2048,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 0,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "SERVER_PORT",
"value": "8081"
},
{
"name": "DB_NAME",
"value": "example_db"
}
],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/dev/ecs/example",
"awslogs-region": "us-west-1",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"family": "bar",
"taskRoleArn": "arn:aws:iam::111111111111:role/assume-ecs-role",
"executionRoleArn": "arn:aws:iam::111111111111:role/ecs-task-execution-role",
"networkMode": "bridge",
"volumes": [],
"placementConstraints": [],
"requiresCompatibilities": [
"EC2"
]
}
我尝试了下一步:
jq -s 'reduce .[] as $item ({}; reduce ($item | keys_unsorted[]) as $key (.; $item[$key] as $val | ($val | type) as $type | .[$key] = if ($type == "array") then (.[$key] + $val | unique) elif ($type == "object") then (.[$key] + $val) else $val end))' 1.json 2.json
但结果是:
{
"containerDefinitions": [
{
"name": "foo",
"image": "nginx:latest",
"cpu": 1024,
"memory": 4096,
"memoryReservation": 2048,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 0,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "SERVER_PORT",
"value": "8080"
},
{
"name": "DB_NAME",
"value": "example_db"
}
],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/dev/ecs/example",
"awslogs-region": "us-west-1",
"awslogs-stream-prefix": "ecs"
}
}
},
{
"environment": [
{
"name": "SERVER_PORT",
"value": "8081"
}
]
}
],
"family": "bar",
"taskRoleArn": "arn:aws:iam::111111111111:role/assume-ecs-role",
"executionRoleArn": "arn:aws:iam::111111111111:role/ecs-task-execution-role",
"networkMode": "bridge",
"volumes": [],
"placementConstraints": [],
"requiresCompatibilities": [
"EC2"
]
}
任何人都可以帮助找出如何达到正确的结果吗?
像这样的东西就可以了:
(input | .containerDefinitions[0].environment | from_entries) as $new_env
| input | .containerDefinitions[].environment |= ((from_entries + $new_env) | to_entries)
如果不清楚,调用应该如下所示:
jq -n '...' 2.json 1.json
这是一个解决方案,使用 tostream
和 has(1)
从第二个文件读取值,并使用 setpath
在第一个文件中设置它们:
jq 'reduce (input | tostream | select(has(1))) as $i (.; setpath($i[0]; $i[1]))' \
1.json 2.json
以相反的顺序 (2.json 1.json
) 提供文件时,上下文 .
和 input
必须交换:
jq 'reduce (tostream | select(has(1))) as $i (input; setpath($i[0]; $i[1]))' \
2.json 1.json
我正在尝试合并两个 JSON 文件。主要目标是用第二个文件中的 environment
个变量覆盖第一个文件中的 environment
个变量。
第一个文件:
{
"containerDefinitions": [
{
"name": "foo",
"image": "nginx:latest",
"cpu": 1024,
"memory": 4096,
"memoryReservation": 2048,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 0,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "SERVER_PORT",
"value": "8080"
},
{
"name": "DB_NAME",
"value": "example_db"
}
],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/dev/ecs/example",
"awslogs-region": "us-west-1",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"family": "bar",
"taskRoleArn": "arn:aws:iam::111111111111:role/assume-ecs-role",
"executionRoleArn": "arn:aws:iam::111111111111:role/ecs-task-execution-role",
"networkMode": "bridge",
"volumes": [],
"placementConstraints": [],
"requiresCompatibilities": [
"EC2"
]
}
第二个文件:
{
"containerDefinitions": [
{
"environment": [
{
"name": "SERVER_PORT",
"value": "8081"
}
]
}
]
}
下一个产品必须是:
{
"containerDefinitions": [
{
"name": "foo",
"image": "nginx:latest",
"cpu": 1024,
"memory": 4096,
"memoryReservation": 2048,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 0,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "SERVER_PORT",
"value": "8081"
},
{
"name": "DB_NAME",
"value": "example_db"
}
],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/dev/ecs/example",
"awslogs-region": "us-west-1",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"family": "bar",
"taskRoleArn": "arn:aws:iam::111111111111:role/assume-ecs-role",
"executionRoleArn": "arn:aws:iam::111111111111:role/ecs-task-execution-role",
"networkMode": "bridge",
"volumes": [],
"placementConstraints": [],
"requiresCompatibilities": [
"EC2"
]
}
我尝试了下一步:
jq -s 'reduce .[] as $item ({}; reduce ($item | keys_unsorted[]) as $key (.; $item[$key] as $val | ($val | type) as $type | .[$key] = if ($type == "array") then (.[$key] + $val | unique) elif ($type == "object") then (.[$key] + $val) else $val end))' 1.json 2.json
但结果是:
{
"containerDefinitions": [
{
"name": "foo",
"image": "nginx:latest",
"cpu": 1024,
"memory": 4096,
"memoryReservation": 2048,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 0,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "SERVER_PORT",
"value": "8080"
},
{
"name": "DB_NAME",
"value": "example_db"
}
],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/dev/ecs/example",
"awslogs-region": "us-west-1",
"awslogs-stream-prefix": "ecs"
}
}
},
{
"environment": [
{
"name": "SERVER_PORT",
"value": "8081"
}
]
}
],
"family": "bar",
"taskRoleArn": "arn:aws:iam::111111111111:role/assume-ecs-role",
"executionRoleArn": "arn:aws:iam::111111111111:role/ecs-task-execution-role",
"networkMode": "bridge",
"volumes": [],
"placementConstraints": [],
"requiresCompatibilities": [
"EC2"
]
}
任何人都可以帮助找出如何达到正确的结果吗?
像这样的东西就可以了:
(input | .containerDefinitions[0].environment | from_entries) as $new_env
| input | .containerDefinitions[].environment |= ((from_entries + $new_env) | to_entries)
如果不清楚,调用应该如下所示:
jq -n '...' 2.json 1.json
这是一个解决方案,使用 tostream
和 has(1)
从第二个文件读取值,并使用 setpath
在第一个文件中设置它们:
jq 'reduce (input | tostream | select(has(1))) as $i (.; setpath($i[0]; $i[1]))' \
1.json 2.json
以相反的顺序 (2.json 1.json
) 提供文件时,上下文 .
和 input
必须交换:
jq 'reduce (tostream | select(has(1))) as $i (input; setpath($i[0]; $i[1]))' \
2.json 1.json