I am looking to transform a json response from an API call. I came across 'jq' and experimented with it, but it kept getting out of hand; was unable to get the desired output.
Sample Input JSON:
{
"realtime": {
"status": {
"name": "realtime",
"link": {
"state": "RUNNING",
"link_id": "09-1"
},
"items": [
{
"id": 0,
"state": "RUNNING",
"link_id": "09-1"
},
{
"id": 1,
"state": "STOPPED",
"link_id": "09-1"
}
],
"doc": "origin"
}
},
"cmx": {
"status": {
"name": "cmx",
"link": {
"state": "RUNNING",
"link_id": "09-1"
},
"items": [
{
"id": 0,
"state": "FAILED",
"link_id": "09-1",
"log": "ErrorMsg"
}
],
"doc": "origin"
}
}
}
Expected JSON Output:
{
"realtime.0": {
"name": "realtime",
"state": "RUNNING",
"url": "/link/realtime/",
"item": 0,
"item_state": "RUNNING",
"item_url": "/links/realtime/items/0/"
},
"realtime.1": {
"name": "realtime",
"state": "RUNNING",
"url": "/link/realtime/",
"item": 1,
"item_state": "STOPPED",
"item_url": "/links/realtime/items/1/"x
},
"cmx.0": {
"name": "cmx",
"state": "RUNNING",
"url": "/links/cmx/",
"item": 0,
"item_state": "FAILED",
"item_url": "/links/cmx/items/0/",
"log": "ErrorMsg"
}
}
The best I got was with command below:
.[]|.status | .name as $name |.link.state as $state| .items[] | {$name, $state,items:[.]}| del(.items[].link_id)
Which resulted in below (not even close):
{
"name": "realtime",
"state": "RUNNING",
"items": [
{
"id": 0,
"state": "RUNNING"
}
]
}
{
"name": "realtime",
"state": "RUNNING",
"items": [
{
"id": 1,
"state": "STOPPED"
}
]
}
{
"name": "cms",
"state": "RUNNING",
"items": [
{
"id": 0,
"state": "FAILED",
"log": "Error"
}
]
}
Appreciate the help. Also, it will very helpful in understanding the solution if an explanation to the steps / filters applied is given.
Thanks!!
CodePudding user response:
Here's one straightforward way using with_entries
, which lets you manipulate the .key
and .value
fields for each item. Here, we store (iterate over) the items of the .status.items
array in a variable, and piece together all the fields needed, either from the current .value
(context) or from the current $item
(variable).
with_entries(
.value.status.items[] as $item
| .key = ".\($item.id)"
| .value |= {
name: .status.name,
state: .status.link.state,
url: "/link/\(.status.name)/",
item: $item.id,
item_state: $item.state,
item_url: "/link/\(.status.name)/items/\($item.id)/",
log: $item.log
}
)
{
"realtime.0": {
"name": "realtime",
"state": "RUNNING",
"url": "/link/realtime/",
"item": 0,
"item_state": "RUNNING",
"item_url": "/link/realtime/items/0/",
"log": null
},
"realtime.1": {
"name": "realtime",
"state": "RUNNING",
"url": "/link/realtime/",
"item": 1,
"item_state": "STOPPED",
"item_url": "/link/realtime/items/1/",
"log": null
},
"cmx.0": {
"name": "cmx",
"state": "RUNNING",
"url": "/link/cmx/",
"item": 0,
"item_state": "FAILED",
"item_url": "/link/cmx/items/0/",
"log": "ErrorMsg"
}
}