Reputation: 99
I have a json like this but much longer:
[
{
"id": "123",
"name": "home network configuration",
"description": "home utilities",
"definedRanges": [
{
"id": "6500b67e",
"name": "100-200",
"beginIPv4Address": "192.168.090.100",
"endIPv4Address": "192.168.090.200",
"state": "UNALLOCATED"
}
]
},
{
"id": "456",
"name": "lab network configuration",
"description": "lab experiments",
"definedRanges": [
{
"id": "1209b90d",
"name": "100-200",
"beginIPv4Address": "192.168.090.100",
"endIPv4Address": "192.168.090.200",
"state": "ALLOCATED"
},
{
"id": "99e08ca4",
"name": "100-200",
"beginIPv4Address": "192.168.090.100",
"endIPv4Address": "192.168.090.200",
"state": "UNALLOCATED"
}
]
}
]
I'd like to query with jq and obtain the following:
[
{
"name": "home network configuration"
"definedRanges": [
{
"name": "100-200",
"beginIPv4Address": "192.168.090.100",
"endIPv4Address": "192.168.090.200",
}
]
},
{
"name": "lab network configuration",
"definedRanges": [
{
"name": "100-200",
"beginIPv4Address": "192.168.090.100",
"endIPv4Address": "192.168.090.200",
},
{
"name": "100-200",
"beginIPv4Address": "192.168.090.100",
"endIPv4Address": "192.168.090.200",
}
]
}
]
or even this:
[
{
"name": "home network configuration",
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200",
},
{
"name": "lab network configuration",
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200",
},
{
"name": "lab network configuration",
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200",
}
]
So far I was able to extract the network name at the first level with:
.[] | {name}
I could also extract the definedRanges with:
.[].definedRanges[] | {name,beginIPv4Address,endIPv4Address}
But I can't figure out how to merge the two with jq.
I solved the problem with a very simple python script (7 lines of code) but now I'd like to understand how to do the same with jq, out of curiosity.
Upvotes: 0
Views: 238
Reputation: 265221
Here's my shot at solutions to produce one or the other desired output:
map(
{ name }
+ (.definedRanges[] | {
"definedRanges.name": .name,
"definedRanges.beginIPv4Address": .beginIPv4Address,
"definedRanges.endIPv4Address": .endIPv4Address
}))
Output:
[
{
"name": "home network configuration",
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200"
},
{
"name": "lab network configuration",
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200"
},
{
"name": "lab network configuration",
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200"
}
]
Producing the first kind of output is even simpler (IMHO it reads a bit more straightforward):
map({
name,
definedRanges: .definedRanges | map({ name, beginIPv4Address, endIPv4Address })
})
Output:
[
{
"name": "home network configuration",
"definedRanges": [
{
"name": "100-2001",
"beginIPv4Address": "192.168.090.101",
"endIPv4Address": "192.168.090.201"
}
]
},
{
"name": "lab network configuration",
"definedRanges": [
{
"name": "100-2002",
"beginIPv4Address": "192.168.090.102",
"endIPv4Address": "192.168.090.202"
},
{
"name": "100-2003",
"beginIPv4Address": "192.168.090.103",
"endIPv4Address": "192.168.090.203"
}
]
}
]
Upvotes: 0
Reputation: 43972
The 'or even this' can be achieved using:
map(.name as $name | .definedRanges[] | { name, beginIPv4Address, endIPv4Address} | with_entries(.key = "definedRanges." + .key) | .name = $name)
Which yields:
[
{
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200",
"name": "home network configuration"
},
{
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200",
"name": "lab network configuration"
},
{
"definedRanges.name": "100-200",
"definedRanges.beginIPv4Address": "192.168.090.100",
"definedRanges.endIPv4Address": "192.168.090.200",
"name": "lab network configuration"
}
]
Upvotes: 1
Reputation: 50750
Well, you were close. Here's how you put those together:
map({name, definedRanges: .definedRanges | map({name, beginIPv4Address, endIPv4Address})})
Upvotes: 1