首页 > 解决方案 > jq如何在提取和修改json中的内容时保留父方括号

问题描述

我有下面的 JSON,我需要修改一些元素值,并且只提取 containerDefinitions 中的内容,同时保留方括号。

下面的脚本用于替换所需的值并在 containerDefinitions 内的方括号内提取 json,但省略了方括号。是否有可以保留方括号的附加命令。

echo $TASK_DEFINITION | jq '.taskDefinition.containerDefinitions[0] | ( .environment[] |= if   .name == "SMT_PORT_3306_TCP_ADDR" then .value = "myvalue" elif .name == "SERVER_API_TIMEOUT_SUBSCRIPTIONS_CANCEL_REQUEST" then .value = "myvalue" else . end) | .logConfiguration.options."awslogs-group" = "myvalue" ' > ${TASK_DEFINITION_PATH}/${SERVICE_NAME}2-task-definition.json

输入 JSON

{
   "taskDefinition":{
      "taskDefinitionArn":"some value",
      "containerDefinitions":[
         {
            "name":"common-api-img",
            "environment":[
               {
                  "name":"SERVER_API_TIMEOUT_SUBSCRIPTIONS_CANCEL_REQUEST",
                  "value":"false"
               },
               {
                  "name":"SMT_PORT_3306_TCP_ADDR",
                  "value":"valueToReplace"
               }
            ],
            "mountPoints":[
               
            ],
            "volumesFrom":[
               
            ]
         }
      ],
      "revision":65,
      "volumes":[
         
      ],
      "status":"ACTIVE"
   }
}

预期产出

[
   {
      "name":"common-api-img",
      "environment":[
         {
            "name":"SERVER_API_TIMEOUT_SUBSCRIPTIONS_CANCEL_REQUEST",
            "value":"myvalue"
         },
         {
            "name":"SMT_PORT_3306_TCP_ADDR",
            "value":"myvalue"
         }
      ],
      "mountPoints":[
         
      ],
      "volumesFrom":[
         
      ]
   }
]

标签: jsonbashjq

解决方案


当您将 a[0]放入查询中时,您将丢弃除第一个列表条目之外的所有内容。因此,您不再有列表。因此,没有更多的方括号。

如果您想处理所有项目,而不仅仅是第一个项目(从而生成项目流),并且想将该流放入列表中,您可能希望:

jq '
  .taskDefinition.containerDefinitions | map(
    ( .environment[] |=
      if .name == "SMT_PORT_3306_TCP_ADDR" then
        .value = "myvalue"
      elif .name == "SERVER_API_TIMEOUT_SUBSCRIPTIONS_CANCEL_REQUEST" then
        .value = "myvalue"
      else . end
    ) |
    .logConfiguration.options."awslogs-group" = "myvalue"
  )
'  <<<"$TASK_DEFINITIONS" >"${TASK_DEFINITION_PATH}/${SERVICE_NAME}2-task-definition.json"

请注意删除[0],并使用map()来通过转换函数传递所有列表元素。


另一种方法是使用jq -n, 并将其放入inputs列表中:

jq -n '
  [ inputs |
    .taskDefinition.containerDefinitions[] |
    ( .environment[] |=
      if .name == "SMT_PORT_3306_TCP_ADDR" then
        .value = "myvalue"
      elif .name == "SERVER_API_TIMEOUT_SUBSCRIPTIONS_CANCEL_REQUEST" then
        .value = "myvalue"
      else . end
    ) |
    .logConfiguration.options."awslogs-group" = "myvalue"
  ]
'  <<<"$TASK_DEFINITIONS" >"${TASK_DEFINITION_PATH}/${SERVICE_NAME}2-task-definition.json"

注意添加了 outer[]s,使用了inputs该块内部,使用了-nto 的参数jq,以及使用了之前使用过的[]where [0]


推荐阅读