使用jq在正确的部分中唯一地添加JSON值

时间:2014-09-16 13:49:26

标签: json shell jq

这个问题是我之前提到的早期问题的扩展:Add JSON value in correct section

基本上,我有一个json文件' veggies.json'如下:

{"plants":
  {"veggies":
    [
      {"section":"TUBERS",
        "values":
          [
            {"tuber":"potato","cookstyle":"fry"}
          ]
      },
      {"section":"LEGUMES",
        "values":
          [
            {"legume":"beans","cookstyle":"boil"},
            {"legume":"peanuts","cookstyle":"salted"}
          ]
      }
    ]
  }
}

我想添加另一个块茎" yam",它可以有烹饪风格"煮沸" - 这必须在TUBERS部分下,但是唯一的。意思是,我想添加这个块茎只有它还没有 - 如果它已经存在,我只想用任何" cookstyle"我正在路过 - 它可能是cookstyle:" mashed"同样。

从我的earlier question,我已经使用' jq'工具:

jq '(.plants.veggies[] | select(.section == "TUBERS") | .values) |= . + [{"cookstyle": "boil", "tuber": "yam"}]' veggies.json

然而,这行代码在TUBERS部分下多次添加相同的行 - 是否有任何方法可以添加它(哈希行为)

提前非常感谢。

3 个答案:

答案 0 :(得分:0)

这看起来应该工作,但它没有 - 如果没有" yam",则输出为空。

jq '
  if (.plants.veggies[] | select(.section == "TUBERS") | .values)[] | select(.tuber == "yam")
  then . 
  else (.plants.veggies[] | select(.section == "TUBERS") | .values) += [{"tuber":"yam", "cookstyle":"mashed"}]    
  end
' veggies.json 

答案 1 :(得分:0)

好的 - 事实证明我过度思考了整个事情 - 也许它可能作为jq本身的单行,但由于我可以自由地使用shell,我只是检查“yam”是否存在如果没有,请添加它,如果是,则编辑它 - 就像这样:

IS_YAM_PRESENT=`jq '(.plants.veggies[] | select(.section == "TUBERS") | .values[] | select(.tuber == "yam") | .cookstyle)' veggies.json`
if [ -z ${IS_YAM_PRESENT} ]
then
    jq '(.plants.veggies[] | select(.section == "TUBERS") | .values) |= . + [{ "tuber": "yam", "cookstyle": "boiled" }]' veggies.json
else
    jq '(.plants.veggies[] | select(.section == "TUBERS") | .values[] | select(.tuber == "yam")) |= { "tuber": "yam", "cookstyle": "boiled" }' veggies.json
fi

与往常一样,如果有人对此有更好的“精炼”和“更严格”的解决方案,我会很高兴看到它。

干杯! :)

答案 2 :(得分:0)

我认为Lakshminarayanan的解决方案非常接近。如果您不想要复制的山药(如果它已经在阵列中),您可以使用唯一将其删除。 E.g。

   (
       .plants.veggies[]
     | select(.section == "TUBERS")
     | .values

   ) |= (
          . + [ {"cookstyle": "boil", "tuber": "yam"} ]
          | unique
        )

或者考虑将逻辑放在一个单独的函数中,以便在复杂时更容易管理。 E.g。

def addyam:
     . + [ {"cookstyle": "boil", "tuber": "yam"} ]
   | unique
;

   (
       .plants.veggies[]
     | select(.section == "TUBERS")
     | .values

   ) |= addyam