使用 jq 向现有 JSON 数组添加新元素

Posted

技术标签:

【中文标题】使用 jq 向现有 JSON 数组添加新元素【英文标题】:Add new element to existing JSON array with jq 【发布时间】:2017-07-03 20:56:17 【问题描述】:

我想使用jq``add 命令将元素附加到 JSON 文件中的数组,但它不起作用。

report-2017-01-07.json文件:

  
   "report": "1.0",
   "data":   
      "date": "2010-01-07",
      "messages": [  
           
            "date": "2010-01-07T19:58:42.949Z",
            "xml": "xml_samplesheet_2017_01_07_run_09.xml",
            "status": "OK",
            "message": "metadata loaded into iRODS successfully"
         ,
           
            "date": "2010-01-07T20:22:46.949Z",
            "xml": "xml_samplesheet_2017_01_07_run_09.xml",
            "status": "NOK",
            "message": "metadata duplicated into iRODS"
         ,
           
            "date": "2010-01-07T22:11:55.949Z",
            "xml": "xml_samplesheet_2017_01_07_run_09.xml",
            "status": "NOK",
            "message": "metadata was not validated by XSD schema"
         
      ]
   

我正在使用这个命令:

$ cat report-2017-01-07.json 
| jq -s '.data.messages "date": "2010-01-07T19:55:99.999Z", "xml": "xml_samplesheet_2017_01_07_run_09.xml", "status": "OKKK", "message": "metadata loaded into iRODS successfullyyyyy"'
jq: error: syntax error, unexpected '', expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
.data.messages "date": "2010-01-07T19:55:99.999Z", "xml": "xml_samplesheet_2017_01_07_run_09.xml", "status": "OKKK", "message": "metadata loaded into iRODS successfullyyyyy"               
jq: 1 compile error

这是我希望输出的样子:


    "report": "1.0",
    "data": 
        "date": "2010-01-07",
        "messages": [
            "date": "2010-01-07T19:58:42.949Z",
            "xml": "xml_samplesheet_2017_01_07_run_09.xml",
            "status": "OK",
            "message": "metadata loaded into iRODS successfully"
        , 
            "date": "2010-01-07T20:22:46.949Z",
            "xml": "xml_samplesheet_2017_01_07_run_09.xml",
            "status": "NOK",
            "message": "metadata duplicated into iRODS"
        , 
            "date": "2010-01-07T22:11:55.949Z",
            "xml": "xml_samplesheet_2017_01_07_run_09.xml",
            "status": "NOK",
            "message": "metadata was not validated by XSD schema"
        , 
            "date": "2010-01-07T19:55:99.999Z",
            "xml": "xml_samplesheet_2017_01_07_run_09.xml",
            "status": "OKKKKKKK",
            "message": "metadata loaded into iRODS successfullyyyyy"
        ]
    

【问题讨论】:

不太了解,但.data.messages 是一个数组不是问题吗?所以你需要类似 .data.messages.[] 对不起,没用 好的 - 阅读文档并安装 jq(这里有 Windows)并尝试 - 得到与你相同的错误。看起来 Windows shell 在将双引号输入到导致 jq 绊倒的流中的方式上存在问题。无法进行任何工作,因此无法回答您的问题,但您可能想查看在 jq 命令中转义双引号。所以"date" 会变成\"date\" 等等。 如果我使用这个命令,我可以更新所有的日期属性。 jq '.data.messages[].date = "2010-01-07T99:99:99.999Z"' report-2017-01-07.json 但我还不能添加。 我更新了输出 【参考方案1】:

过滤器中的|= .+ 部分将一个新元素添加到现有数组中。您可以将jq 与过滤器一起使用:

jq '.data.messages[3] |= . + "date": "2010-01-07T19:55:99.999Z", "xml": "xml_samplesheet_2017_01_07_run_09.xml", "status": "OKKK", "message": "metadata loaded into iRODS successfullyyyyy"' inputJson

为避免使用硬编码的长度值3并动态添加新元素,请使用返回长度的. | length,该长度可用作下一个数组索引,即

jq '.data.messages[.data.messages| length] |= . + "date": "2010-01-07T19:55:99.999Z", "xml": "xml_samplesheet_2017_01_07_run_09.xml", "status": "OKKK", "message": "metadata loaded into iRODS successfullyyyyy"' inputJson

(或)根据峰值在 cmets 中的建议,单独使用 += 运算符

jq '.data.messages += ["date": "2010-01-07T19:55:99.999Z", "xml": "xml_samplesheet_2017_01_07_run_09.xml", "status": "OKKK", "message": "metadata loaded into iRODS successfullyyyyy"]'

产生你需要的输出:


  "report": "1.0",
  "data": 
    "date": "2010-01-07",
    "messages": [
      
        "date": "2010-01-07T19:58:42.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "OK",
        "message": "metadata loaded into iRODS successfully"
      ,
      
        "date": "2010-01-07T20:22:46.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "NOK",
        "message": "metadata duplicated into iRODS"
      ,
      
        "date": "2010-01-07T22:11:55.949Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "NOK",
        "message": "metadata was not validated by XSD schema"
      ,
      
        "date": "2010-01-07T19:55:99.999Z",
        "xml": "xml_samplesheet_2017_01_07_run_09.xml",
        "status": "OKKK",
        "message": "metadata loaded into iRODS successfullyyyyy"
      
    ]
  

使用jq-play 试运行您的jq-filter 并优化您想要的任何方式。

【讨论】:

由于目标只是追加一个元素,最好使用 += 但值得注意的是,.data.messages[3] |= . + X 在这里可以简化为 .data.messages[3] = X,就像上面的 . RHS 实际上只是 null (windows JQ 用户在这里):我想知道是否可以将这些新数据写入同一个(输入)文件,而不是创建一个需要重命名的临时文件..跨度> @script'n'code - 如果您拥有或可以安装它(它是 moreutils 的一部分),使用 sponge 可能仍然是最佳选择。 @peak 如何将该对象插入到数组的开头,无法弄清楚。谢谢 @peak 如何在将元素插入数组时指定顺序?【参考方案2】:

与其使用|=,不如考虑使用+=

.data.messages += ["date": "2010-01-07T19:55:99.999Z",
   "xml": "xml_samplesheet_2017_01_07_run_09.xml",
   "status": "OKKK", "message": "metadata loaded into iRODS successfullyyyyy"]

前置

另一方面,如果(如@NicHuang 所问)您想将 JSON 对象添加到数组的开头,您可以使用以下模式:

 .data.messages |= [ _ ] + .

【讨论】:

添加示例:echo '"arr": [ "data1" ]' | jq '.arr |= ["data2"] + .' => "arr": ["data2", "data1"]【参考方案3】:

总结:“.+”是你的救星

详情:

要向列表中添加条目:您可以附加 [list1] + [list2](而不是 [list] + data)

$ echo '[ "data1" ]' | jq '. + [ "data2" ]'
[
  "data1",
  "data2"
]

$ echo '[ "key1": "value1" ]' | jq '. + ["key2": "value2"]'
[
  
    "key1": "value1"
  ,
  
    "key2": "value2"
  
]

用于向字典添加键/值:

$ echo '"key1": "value1"' | jq '. + "key2": "value2"'

  "key1": "value1",
  "key2": "value2"

参考资料:

https://gist.github.com/joar/776b7d176196592ed5d8

【讨论】:

以上是关于使用 jq 向现有 JSON 数组添加新元素的主要内容,如果未能解决你的问题,请参考以下文章

使用 JavaScript 向 JSON 对象添加新属性(元素)

C++ 向数组添加元素

jq点击按钮添加元素到数组

js中如何向json数组添加元素

js数组添加元素

Javascript映射函数:向对象添加新键和值[重复]