我从DigitalOcean JSON API获取Droplet列表,并使用jq map将响应转换为我需要的信息。
我希望能够添加一个可选键和&值对应我的新对象,基于响应是否包含具有特定值的键。
如果响应不包含匹配项,则使用select()
时,整个Droplet条目将从我的新对象中删除,而不仅仅是键。
如何过滤单个键而不是整个条目?
详细说明:
单个液滴的响应如下所示:
"id": 12345678,
"name": "my-droplet",
...
"networks": {
"v4": [
{
"ip_address": "123.456.78.90",
"netmask": "255.255.240.0",
"gateway": "123.123.0.1",
"type": "public"
},
{
"ip_address": "10.123.45.67",
"netmask": "255.255.0.0",
"gateway": "10.123.0.1",
"type": "private"
}
],
"v6": []
},
...
我想将其转换为以下形式的对象:
{
"id": 12345678,
"name": "my-droplet",
"public_ip": "123.456.78.90",
"private_ip" "10.123.45.67"
}
所有水滴都有公共IP,但私有IP是可选的。
我有这个,忽略了可选的私有IP,到目前为止工作正常:
jq '.droplets | map({id: .id, name: .name, status: .status, public_ip: .networks.v4[] | select(.type=="public") | .ip_address})'
但是,一旦我添加私有IP,任何没有一个的Droplet都会从响应中丢失:
jq '.droplets | map({id: .id, name: .name, status: .status, public_ip: .networks.v4[] | select(.type=="public") | .ip_address, private_ip: .networks.v4[] | select(.type=="private") | .ip_address})'
我认为我需要使用串联或条件,但我无法弄清楚语法。
注意:我发现了类似的问题,但它并未包含更改密钥的名称:denormalizing JSON with jq
答案 0 :(得分:1)
如果没有私人IP(或者确实存在多个私人IP),您没有准确指出应该发生什么,但以下内容应该让您继续前进。
.droplets
| map({id, name, status,
public_ip: (first(.networks.v4[] | select(.type=="public")) // {})
| .ip_address,
private_ip: (first(.networks.v4[] | select(.type=="private")) // {})
| .ip_address } )
def one(condition): first(.[] | select(condition)) // null;
.droplets
| map({id, name, status}
+ (.networks.v4
| { public_ip: one(.type=="public") | .ip_address}
+ (one(.type=="private")
| if . then {private_ip: .ip_address} else null end ) ))