如何使用jq在JSON文件中添加嵌套键/值

时间:2017-10-05 02:22:57

标签: json shell jq

我对jq命令很新,并且卡在一个编辑JSON文件的地方。我有一个JSON文件,格式如下。

{
  "service": {
    "name": "web",
    "tags": [
      "contact_points"
    ],
    "check": {
      "script": "tmp/status_check.py > /dev/null 2>&1",
      "interval": "10s"
    }
  }
}

我想修改此JSON以添加嵌套键/值,如下所示:

{
"service": [{
        "name": "web",
        "tags": [
            "contact_points"
        ],
        "check": {
            "script": "tmp/status_check.py > /dev/null 2>&1",
            "interval": "10s"
        }
    },
    {
        "name": "tomcat",
        "tags": [
            "contact_points"
        ],
        "check": {
            "script": "tmp/status_check.py > /dev/null 2>&1",
            "interval": "10s"
        }
    }
]

}

我尝试了以下命令,但它会覆盖文件的内容。

  

jq'。 + {" service":" {" name":" tomcat"," tags":[" contact_points&# 34;],"检查":{"脚本":" tmp / status_check.py> / dev / null 2>& 1"," interval":" 10s"}}" }' /tmp/status.json> / tmp / file&& mv / tmp / file /tmp/status.json

并给出以下输出

{
  "service": {
    "name": "tomcat",
    "tags": [
      "contact_points"
    ],
    "check": {
      "script": "tmp/status_check.py > /dev/null 2>&1",
      "interval": "10s"
    }
  }
}

我尝试转义特殊字符,但无法获得所需的输出。有没有其他方法来实现这一目标?非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

感谢您更新问题。由于在您的输入中.service是一个对象,而在您的输出中.service是一个数组,这里是一个使用辅助函数的解决方案:

def as_array:if type=="object" then [.] else . end;

.service |= as_array + [
   {
     "name": "tomcat",
     "tags": [
       "contact_points"
     ],
     "check": {
        "script": "tmp/status_check.py > /dev/null 2>&1",
        "interval": "10s"
     }
   }
]

如果上述过滤器位于filter.jq且您的样本数据位于status.json,则命令

$ jq -M -f filter.jq status.json

产生

{
  "service": [
    {
      "name": "web",
      "tags": [
        "contact_points"
      ],
      "check": {
        "script": "tmp/status_check.py > /dev/null 2>&1",
        "interval": "10s"
      }
    },
    {
      "name": "tomcat",
      "tags": [
        "contact_points"
      ],
      "check": {
        "script": "tmp/status_check.py > /dev/null 2>&1",
        "interval": "10s"
      }
    }
  ]
}

如果您想使用此输出替换现有的status.json,可以使用sponge(1)中的moreutils等解决方案,例如

$ jq -M -f filter.jq status.json | sponge status.json

答案 1 :(得分:0)

如果你的目标只是采用单一服务并使用新名称复制它,那么你可以这样做:

.service |= [., .name = "tomcat"]

https://jqplay.org/s/33L3zA9Fos

即,通过创建包含当前项的数组以及.service |= ...属性为name的另一个副本来更新服务属性("tomcat")。