【问题标题】:Conditionally add element to json array using jq使用 jq 有条件地将元素添加到 json 数组
【发布时间】:2015-08-23 14:01:22
【问题描述】:

我正在使用 jq 将字符串添加到 JSON 数组,效果很好,但我只想添加尚不存在的字符串。我已经尝试过独特的、有的、没有的等。我错过了一个或两个拼图。

这是我的起始 json 文件,foo.json:

{
  "widgets": [
    {
      "name": "foo",
      "properties": [
        "baz"
      ]
    },
    {
      "name": "bar"
    }
  ]
}

这是我构建的用于添加字符串的 jq 命令,即使它已经存在:

$ cat foo.json | jq '.widgets[] | select(.name=="foo").properties |= .+ ["cat"]'

这是我尝试的最新版本。

$ cat foo.json | jq '.widgets[] | select(.name=="foo").properties | has("cat") | not | .properties += ["cat"]'
jq: error: Cannot check whether array has a string key

【问题讨论】:

  • 注意:我需要打印整个文件,我的迭代没有考虑到这一点。
  • 我解决了这个问题: jq '.widgets[] |= (select(.name=="foo").properties |= (.+ ["cat"] | unique))'

标签: json jq


【解决方案1】:

有很多方法可以做到这一点。

假设数组的元素应该是唯一的,您的用例强烈暗示了这一点,您可以通过 unique 过滤器将添加后的结果数组传递。

$ cat foo.json | jq '.widgets[] | select(.name=="foo").properties |= (.+ ["cat"] | unique)'

【讨论】:

  • 太棒了,这正是我想要的。我误解了 unique 的使用,但现在它已经到位了。
  • 我现在意识到这种方法使 widgets[] 成为根元素。解决这个问题的最佳方法是什么?
  • 圣地亚哥,添加代码时,总是缩进4个空格,不要使用反引号。仅用于突出显示关键字和其他内联内容。
  • @JeffMercado 注意!感谢您的反馈:)
  • @brian 用括号将|= 的左侧包裹起来应该可以。
【解决方案2】:

正如他们所说,给猫剥皮的方法不止一种,但也许这会给你一些想法:

.widgets[]
| select(.name=="foo")
| select(.properties | index("cat") | not)
| .properties += ["cat"]

根据您的输入,结果是:

{
  "name": "foo",
  "properties": [
    "baz",
    "cat"
  ]
}

以下内容可能更接近您的要求:

.widgets |= [ .[] | if .properties|index("cat")|not
                    then .properties += ["cat"]
                    else .
                    end]

【讨论】:

  • 嗯..有趣!我对其进行了测试,并且我同意它可以按照您所引用的那样工作,但是如果 cat 已经存在,则它什么也不会打印。它只打印 foo 小部件,但我想我可以通过 '(expr) | .[0]'.
  • 您的第二个示例很有帮助 - 但它没有按名称过滤。
  • 我想我已经解决了 - 谢谢。你给了我一个帮助我弄清楚的想法。
猜你喜欢
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-03
  • 2014-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多