【问题标题】:jq - Find a JSON object based on one of its values and get another value from itjq - 根据其中一个值查找 JSON 对象并从中获取另一个值
【发布时间】:2018-07-27 13:11:42
【问题描述】:

我最近才开始使用 jq,我想知道这样的事情是否可行。

例子:

{
  "name": "device",
  "version": "1.0.0",
  "address": [
    {
      "address": "10.1.2.3",
      "interface": "wlan1_wifi"
    },
    {
      "address": "10.1.2.5",
      "interface": "wlan2_link"
    },
    {
      "address": "10.1.2.4",
      "interface": "ether1"
    }
  ],
  "wireless": [
    {
      "name": "wlan1_wifi",
      "type": "5Ghz",
      "ssid": "wifi"
    },
    {
      "name": "wlan2_link",
      "type": "2Ghz",
      "ssid": "link"
    }
  ]
}

首先让我们将示例转换为这个 json 对象:

cat json | jq '. | {"name": ."name", "version": ."version", "wireless": [."wireless"[] | {"name": ."name", "type": ."type", "ssid": ."ssid"}]}'
{
  "name": "device",
  "version": "1.0.0",
  "wireless": [
    {
      "name": "wlan1_wifi",
      "type": "5Ghz",
      "ssid": "wifi"
    },
    {
      "name": "wlan2_link",
      "type": "2Ghz",
      "ssid": "link"
    }
  ]
}

现在有一个问题。我需要为"wireless" 数组分配一个地址。地址存储在"address"数组中。

所以问题是:有没有一种方法可以根据"name"(在无线阵列中)和“interface"(在地址阵列中)在"address" 中为@ 中的每个json 对象找到正确的json 对象987654330@ 数组,然后将"address" 分配给它?

最终的结果应该是这样的:

{
  "name": "device",
  "version": "1.0.0",
  "wireless": [
    {
      "name": "wlan1_wifi",
      "type": "5Ghz",
      "ssid": "wifi",
      "address": "10.1.2.3"
    },
    {
      "name": "wlan2_link",
      "type": "2Ghz",
      "ssid": "link",
      "address": "10.1.2.5"
    }
  ]
}

答案: 这是我基于来自@peak 的answer 的答案。我不是复制.wireless 的内容然后使用map,而是挑选我只想包含的键。这也让我可以随意定位“地址”。

(INDEX(.address[]; .interface)) as $dict 
| {name: .name, version: .version, 
wireless: [.wireless[] | {name, address: ($dict[.name]|.address), type, ssid}]}

【问题讨论】:

  • 请花时间创建一个小例子,而不是把一堆现实世界的数据放到问题中
  • Josef - 是的,这是可能的,但请参阅 minimal reproducible example
  • 对不起@hek2mgl,现在应该没问题了
  • 酷!现在看起来好多了。

标签: json jq


【解决方案1】:

以下产生最初要求的输出:

(.wireless[].name) as $name
| .address[]
| select(.interface == $name)
| { wireless: {name: $name, address}}

但是,上述过滤器可能会产生多个结果,因此您可能需要相应地进行修改。

修订修订要求

如果您的 jq 有 INDEX/2(仅在 jq 1.5 发布后可用),您可以简单地使用它来创建查找表:

(INDEX(.address[]; .interface)) as $dict
| {name,
   version,
   wireless: (.wireless
              | map(. + {address: ($dict[.name]|.address) }) ) }

或者(可能取决于具体要求):

(INDEX(.address[]; .interface)) as $dict
| del(.address)
| .wireless |= map(. + {address: ($dict[.name]|.address) })

如果你的 jq 没有INDEX/2,那么你可以轻松地修改上面的内容(使用reduce),或者更容易从https://github.com/stedolan/jq/blob/master/src/builtin.jq 中获取INDEX/2 的def

【讨论】:

  • 谢谢!这适用于最小的示例,但是我无法从“无线”数组传递附加值。假设“无线”数组中的每个对象都有额外的键/值对“ssid”。如何在“无线”对象的最终输出中显示它?谢谢!
  • 我建议您在原始问题中添加一个附录,再次遵循 minimal reproducible example 指南。
  • “wifi”从何而来?从 .interface 字符串的后缀?
  • 没有。它来自“无线”数组中的对象,因此与“名称”来自同一个地方。键的值可以变化。
  • 您似乎忘记了minimal reproducible example 原则。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 2017-08-03
  • 1970-01-01
  • 2015-12-02
  • 2020-11-25
  • 2021-11-07
  • 1970-01-01
相关资源
最近更新 更多