如果 child 具有特定的 key:value,则将键值添加到 parent 子元素

Add key value to parent subelement if child has specific key:value

我正在尝试了解将 json 元素添加到 child 的 parent 的最佳方法是什么 如果 child 包含特定的 key:value 并最终使用 jq 打印整个 json 我试着用一个例子更好地解释。 输入json是:

{
  "family": {
    "surname": "Smith"
  },
  "components": [
    {
      "name": "John",
      "details": {
        "hair": "brown",
        "eyes": "brown",
        "age": "56"
      },
      "role": "father"
    },
    {
      "name": "Mary",
      "details": {
        "hair": "blonde",
        "eyes": "green",
        "age": "45"
      },
      "role": "mother"
    },
    {
      "name": "George",
      "details": {
        "hair": "blonde",
        "eyes": "brown",
        "age": "25"
      },
      "role": "child"
    }
  ]
}

我要补充: "description": "5 年未满 30 岁" 如果“年龄”等于“25”,则在“详细信息”的同一级别,然后打印结果:

{
  "family": {
    "surname": "Smith"
  },
  "components": [
    {
      "name": "John",
      "details": {
        "hair": "brown",
        "eyes": "brown",
        "age": "56"
      },
      "role": "father"
    },
    {
      "name": "Mary",
      "details": {
        "hair": "blonde",
        "eyes": "green",
        "age": "45"
      },
      "role": "mother"
    },
    {
      "name": "George",
      "details": {
        "hair": "blonde",
        "eyes": "brown",
        "age": "25"
      },
      "role": "child",
      "description": "5 years less than 30"
    }
  ]
}

我找到的唯一解决方案是应用更新但只打印“组件”内容; 然后我从JSON中删除并最终插入之前保存的修改后的“组件”内容,这样:

cat sample.json | jq -c ' .components[] | select(.details.age=="25") |= . + {description: "5 years less than 30" } ' > /tmp/saved-components.tmp
cat sample.json | jq --slurpfile savedcomponents /tmp/saved-components.tmp 'del(.components) | . + { components: [ $savedcomponents ] }'

我认为这不是解决此类问题的最佳方法,所以我想知道什么是 正确的“jq 方法”。 忘了说了:我比较喜欢只用jq,其他工具都不用

比你

马可

您可以select匹配条件的对象并附加到该对象。像下面这样的东西。关键是使用+=修饰赋值不丢失其他对象

(.components[] | select(.details.age == "25")) += { "description": "5 years less than 30" }

jqplay - Demo

这是一个简单(“没有魔法”)且有效的解决方案:

.components |= 
  map(if .details.age=="25" then .description = "5 years less than 30" else . end)