使用jq更新JSON对象列表中的一个值(匹配已知键)

时间:2017-12-27 20:39:52

标签: json bash jq

我有以下格式的多个json文件作为环境文件,需要针对端点进行测试,

{
  "id": "test1123",
  "name": "my testing",
  "values": [
    {
      "enabled": true,
      "key": "URL",
      "value": "http://localhost:3000/",
      "type": "text"
    },
    {
      "enabled": true,
      "key": "User1Token",
      "value": "",
      "type": "text"
    },
    {
      "enabled": true,
      "key": "User2Token",
      "value": "",
      "type": "text"
    },
    {
      "enabled": true,
      "key": "IdentityURL",
      "value": "",
      "type": "text"
    },
    {
      "enabled": true,
      "key": "AdminToken",
      "value": "",
      "type": "text"
    }
  ],
  "timestamp": 1511892974802,
  "_postman_variable_scope": "environment",
  "_postman_exported_at": "2017-11-28T19:38:23.389Z",
  "_postman_exported_using": "Postman/5.3.0"
}

我想在运行测试之前更新此json中的终点。需要将端点值添加到值对象的value属性,其中键为" URL"

所以在上面的例子中,我应该在第一个值数组索引

中更新端点
{
  "enabled": true,
  "key": "URL",
  "value": "http://10.20.200.1/",
  "type": "text"
}

其中http://10.20.200.1/是我的终点。

我尝试使用的当前代码是:

jq '.values | map(if .key == "URL" then . + {"value":"10.20.13.28/";} else . end )'

...但这会导致语法错误。任何人都可以建议我如何使用jq正确更新值?

注意:关键网址永远不会是第一个价值指数。

2 个答案:

答案 0 :(得分:3)

如果要保留其他周围的键/值对并仅更新values项,则需要为其计算新值。这样做可能如下所示:

jq \
  --arg updateKey "URL" \
  --arg updateVal "http://10.20.200.1" \
  '.values = [.values[] | if (.key == $updateKey) then (.value = $updateVal) else . end]'

答案 1 :(得分:2)

以下只是@ CharlesDuffy的优秀答案的变体:

def when(c; f): if c? // null then f else . end;

.values = map( when(.key == $updateKey; .value = $updateVal) )

when/2的这个定义非常通用。它增加了一小部分安全性,避免了if _ then _ else . end的单调乏味。它可能值得你的标准jq库(例如〜/ .jq或〜/ .jq / jq / jq.jq)。