jq: combine multi array in dict without permutate - jq

are there have any way to achieve simply as expected?
it using combine with permutate in default.
The Following Case
source
{
"title":["title1","title2"],
"link":["http://testapi.cn","http://testapi.org"]
}
expression [{title:.title[],link:.link[]}]
console
[
{
"title": "title1",
"link": "http://testapi.cn"
},
{
"title": "title1",
"link": "http://testapi.org"
},
{
"title": "title2",
"link": "http://testapi.cn"
},
{
"title": "title2",
"link": "http://testapi.org"
}
]
expected
[
{
"title": "title1",
"link": "http://testapi.cn"
},
{
"title": "title2",
"link": "http://testapi.org"
}
]

Use transpose to generate an array of arrays with one element of each input array.
[.title,.link] | transpose | map({title:.[0],link:.[1]})

Related

`jq` hangs when I provide `--arg` and a template json

I am trying to use jq to create a json from a template json file using --args and the template file. When I execute the below command, jq just hangs in there forever.
I am a rookie with jq, would really appreciate if someone can point out what am I doing wrong.
template.jq
{
"channel": "channel",
"attachments": [
{
"color": "#a7dbb5",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": $SUMMARY,
"emoji": true
}
},
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Build ID: * <\($BUILD_URL)|\($BUILD_ID)>\n*Duration:* \($DURATION)\n*User: *<\($USER_EMAIL)|\($USER_NAME)>\n*Test Cases:* \($TEST_CASES)"
},
"accessory": {
"type": "image",
"image_url": "https://raw.githubusercontent.com/sudas-px/dev-repo/main/check.png",
"alt_text": "status thumbnail"
}
},
{
"type": "divider"
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Portworx*\nv\($PX_VERSION)"
},
{
"type": "mrkdwn",
"text": "*PX Backup*\nv\($PX_BACKUP_VERSION)"
}
]
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Stork Image:*\n\($STORK_IMAGE)"
},
{
"type": "mrkdwn",
"text": "*Kubernetes:*\nv\($K8S_VERSION)"
}
]
},
{
"type": "divider"
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Github Repository*"
},
{
"type": "mrkdwn",
"text": $GITHUB_REPO
}
]
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Branch*"
},
{
"type": "mrkdwn",
"text": $GITHUB_BRANCH
}
]
},
{
"type": "divider"
},
{
"type": "actions",
"block_id": "actionblock789",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "View Pipeline"
},
"style": "primary",
"url": $BUILD_URL
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "View Logs"
},
"url": $KIBANA_URL
}
]
}
]
}
]
}
This is the command I ran
jq --arg SUMMARY "Summary" --arg BUILD_ID "BUILD_ID" --arg BUILD_URL "BUILD_URL" --arg DURATION "DURATION" --arg USER_EMAIL "EMAIL" --arg USER_NAME "USER" --arg TEST_CASES 3 --arg PX_VERSION "VERSION" --arg PX_BACKUP_VERSION "PX_VERSION" --arg STORK_IMAGE "IMAGE_STORK" --arg K8S_VERSION "1.23.0" --arg GITHUB_BRANCH "branch" --arg GITHUB_REPO "repo" --arg KIBANA_URL "url" -f template.jq
Your "template" is just a filter that requires no input, but you forgot to tell jq that the filter won't need any input. As a result, jq is waiting to read from standard input. Use the -n option to tell jq it doesn't need to read from standard input.
jq -n <lots of --args> -f template.jq

transform json input using jq command

I have the following json input from a internet service:
{
"sunarme": "foo",
"id": "foo-id",
"name": "Foo bar",
"profile": [
{
"id": "test1",
"products": [
"product1",
"product2"
],
"description": "test1 description"
},
{
"id": "test2",
"products": [
"product3",
"product4",
"product5"
],
"description": "test2 description"
},
{
"id": "test3",
"products": [
"product6",
"product7",
"product8"
],
"description": "test2 description"
}
]
}
So I need to transform profile key from array to json object. This is the desired output:
{
"sunarme": "foo",
"id": "foo-id",
"name": "Foo bar",
"profile": {
"test1": [
"product1",
"product2"
],
"test2": [
"product3",
"product4",
"product5"
],
"test3": [
"product6",
"product7",
"product8"
]
}
}
I don't have any idea how to do it in jq command, please, could you help me?
Thanks in advance.
Use with_entries which lets you convert the array into an object if you adjust the .keys accordingly.
jq '.profile |= with_entries(.key = .value.id | .value |= .products)'
Demo
Or use reduce to build the object by iterating through the array.
jq '.profile |= reduce .[] as $p ({}; .[$p.id] = $p.products)'
Demo
Or use map to convert each array item into an object, then merge them using add.
jq '.profile |= (map({(.id): .products}) | add)'
Demo
Output is:
{
"sunarme": "foo",
"id": "foo-id",
"name": "Foo bar",
"profile": {
"test1": [
"product1",
"product2"
],
"test2": [
"product3",
"product4",
"product5"
],
"test3": [
"product6",
"product7",
"product8"
]
}
}

jq - extract multiple fields from a list, with a nested list of key/value pairs

I have the following structure:
{
"Subnets": [
{
"SubnetId": "foo1",
"Id": "bar1",
"Tags": [
{
"Key": "Name",
"Value": "foo"
},
{
"Key": "Status",
"Value": "dev"
}
]
},
{
"SubnetId": "foo2",
"Id": "bar2",
"Tags": [
{
"Key": "Name",
"Value": "foo"
},
{
"Key": "Status",
"Value": "dev"
}
]
}
]
}
I can extract multiple keys at the "top level" like so:
cat subnets.json| jq '.Subnets[] | "\(.Id) \(.SubnetId)"'
Anyone know how I can also display one of the tags by key name, let's say I also want the Status tag displayed on the same line as the Id and SubnetId.
Thx for any help,
Is this what you are looking for?
jq '.Subnets[] | "\(.Id) \(.SubnetId) \(.Tags | from_entries | .Status)"' subnets.json

Conditional select using jq

I have this below json format, I want to take the list of "id" which satisfies the condition
in this below I want to take the id which has matchers.value as dev-stack and status.state as active
{
"status": "success",
"data": [
{
"id": "b5e7f85d",
"matchers": [
{
"name": "stack",
"value": "dev-stack",
"isRegex": true
}
],
"startsAt": "2020-07-13T07:17:36Z",
"endsAt": "2020-07-15T07:15:44Z",
"updatedAt": "2020-07-13T07:15:59.643692023Z",
"createdBy": "api",
"comment": "Silence",
"status": {
"state": "active"
}
},
{
"id": "1fdaa4b5",
"matchers": [
{
"name": "stack",
"value": "qa-stack",
"isRegex": true
}
],
"startsAt": "2020-07-10T13:19:12Z",
"endsAt": "2020-07-10T13:20:55.510739499Z",
"updatedAt": "2020-07-10T13:20:55.510739499Z",
"createdBy": "api",
"comment": "Silence",
"status": {
"state": "expired"
}
}
]
}
Here is a solution which uses update assignment |=, map and select to update .data.
Note it avoids an undesirable cartesian product if multiple .matchers meet the criteria by using any.
.data |= map(select(
(.matchers | any(.value=="dev-stack")) and (.status.state=="active")
))
Try it online!

Use jq extract two values and build new output

Looking to extract values from api_http array. I am looking for output that looks like the following. Each element should have the name and the url value attached a key called api.
{ "name": "lookproduct1", "api": "http://testapi.api.com"}
{ "name": "lookproduct2", "api": "http://testapi2.api.com"}
{ "name": "lookproduct3", "api": "http://testapi3.api.com"}
{ "name": "lookproduct4", "api": "http://testapi4.api.com"}
the JSON data:
{
"meta": {
"details": {
"value": "Details"
},
"network": {
"label": "Network:",
"value": "test"
},
"title": {
"value": "Test Report"
},
"update": {
"label": "Validation last update:",
"value": "2020-07-15 17:40 UTC"
}
},
"report": {
"api_http": [
[
{
"html_name": "Product 1",
"name": "lookproduct1",
"rank": 3
},
"http://testapi.api.com",
"GB",
"TEST"
],
[
{
"html_name": "Product 2",
"name": "lookproduct2",
"rank": 3
},
"http://testapi2.api.com",
"GB",
"TEST"
],
[
{
"html_name": "Product 3",
"name": "lookproduct3",
"rank": 3
},
"http://testapi3.api.com",
"GB",
"TEST"
],
[
{
"html_name": "Product 4",
"name": "lookproduct4",
"rank": 3
},
"http://testapi.api.com",
"GB",
"TEST"
]
]
}
}
I got the following, but unsure to extract those final two values and create the new output.
.report[] | .[]
Try:
.report.api_http[]|{name:values[0]["name"],api:values[1]}
My output is:
{
"name": "lookproduct1",
"api": "http://testapi.api.com"
}
{
"name": "lookproduct2",
"api": "http://testapi2.api.com"
}
{
"name": "lookproduct3",
"api": "http://testapi3.api.com"
}
{
"name": "lookproduct4",
"api": "http://testapi.api.com"
}
You could use the -c command-line option in conjunction with the following jq filter:
.report.api_http[]
| {name: .[0].name, api: .[1]}

Resources