I have a json like this
[{"version": 0.0,"Resources": [ {"TargetService": {"Type": "AWS::ECS::Service","Properties": {"TaskDefinition": "abc","LoadBalancerInfo": {"ContainerName": "def","ContainerPort": 8080}}}} ]}]
My attempt is to replace TaskDefinition key value from "abc" to "123" and ContainerName key value from "def" to "456 in one command and return the whole update json.
This is what i tried
echo $APP_SPEC | jq --arg TASK_DEFINITION "123" '(.[].Resources[].TargetService | select(.Properties)).TaskDefinition |=$TASK_DEFINITION')
But the substistuion is not happening properly and the value gets appended at the end of the josn as below.
Incorrect response:
[ { "version": 0, "Resources": [ { "TargetService": { "Type": "AWS::ECS::Service", "Properties": { "TaskDefinition": "abc", "LoadBalancerInfo": { "ContainerName": "container_name", "ContainerPort": 8080 } }, "TaskDefinition": "123" } } ] } ]
>Solution :
Use the update operator |=
.[].Resources[].TargetService.Properties |= (
.TaskDefinition = "123"
| .LoadBalancerInfo.ContainerName = "456"
)
Note that select only filters its input, it does not descend into the filter criterion. So, if you only want to make the update if the .Properties field exists, use select and descend into it.
( .[].Resources[].TargetService
| select(.Properties).Properties
) |= (
.TaskDefinition = "123"
| .LoadBalancerInfo.ContainerName = "456"
)
Note that the filter select(.Properties) will produce false if the content of that field, albeit existing, evaluates to null or false. If you want to consider such cases also as "existent", use has in the select filter to test for it.
( .[].Resources[].TargetService
| select(has("Properties")).Properties
) |= (
.TaskDefinition = "123"
| .LoadBalancerInfo.ContainerName = "456"
)