使用 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 数组添加新元素的主要内容,如果未能解决你的问题,请参考以下文章