How to parse input with jq - json

I have the list of docker images in json, for example:
{
"name": "chart1",
"version": "1.1.0",
"appVersion": "1.1.0",
"dependencies": [
{
"name": "name1",
"version": "10000.1.wew2133"
},
{
"name": "name2",
"version": "10001.1.wew2133"
}
]
}
I need to convert this to list:
name1:10000.1.wew2133
name2:10001.1.wew2133
How can I do this?

Use join(":"):
jq --raw-output '.dependencies[] | join(":")'
name1:10000.1.wew2133
name2:10001.1.wew2133
JQPlay demo

Related

How to get a value from json based on key in bash

I'm trying to extract value of a branch from the below json/test.json file using jq
{
"pipeline": {
"name": "test",
"roleArn": "arn:aws:iam::1234:role/service-role/AWSCodePipelineServiceRole-us-west-2-test",
"artifactStore": {
"type": "S3"
},
"stages": [{
"name": "Source",
"actions": [{
"name": "Source",
"actionTypeId": {
"category": "Source",
"version": "1"
},
"runOrder": 1,
"configuration": {
"Branch": "experiment"
}
}]
}],
"version": 1
}
}
Below is jq command I'm using jq -r '.pipeline.stages.actions.configuration.Branch' test.jsonwhich returns jq: error (at test.json:76): Cannot index array with string "actions". I'm I missing something here
When you're doing queries, and something doesn't work at first, then try something simple and keep adding to it. So in your case, start with
$ jq -r '.pipelines' test.json
null
Aha, it's "pipeline" not "pipelines", so go from there:
$ jq -r '.pipeline' test.json
{
"name": "test",
"roleArn": "arn:aws:iam::1234:role/service-role/AWSCodePipelineServiceRole-us-west-2-test",
"artifactStore": {
"type": "S3"
},
"stages": [
{
"name": "Source",
"actions": [
{
"name": "Source",
"actionTypeId": {
"category": "Source",
"version": "1"
},
"runOrder": 1,
"configuration": {
"Branch": "experiment"
}
}
]
}
],
"version": 1
}
So that works. Now we want to get to "stages" so we do this
$ jq -r '.pipeline.stages' test.json
[
{
"name": "Source",
"actions": [
{
"name": "Source",
"actionTypeId": {
"category": "Source",
"version": "1"
},
"runOrder": 1,
"configuration": {
"Branch": "experiment"
}
}
]
}
]
Note that "stages" gives you an array, not just a hash, so you have to refer to [0], the zeroth element.
$ jq -r '.pipeline.stages[0]' test.json
{
"name": "Source",
"actions": [
{
"name": "Source",
"actionTypeId": {
"category": "Source",
"version": "1"
},
"runOrder": 1,
"configuration": {
"Branch": "experiment"
}
}
]
}
Now you can get to "actions"
$ jq -r '.pipeline.stages[0].actions' test.json
[
{
"name": "Source",
"actionTypeId": {
"category": "Source",
"version": "1"
},
"runOrder": 1,
"configuration": {
"Branch": "experiment"
}
}
]
and then the zeroth one
$ jq -r '.pipeline.stages[0].actions[0]' test.json
{
"name": "Source",
"actionTypeId": {
"category": "Source",
"version": "1"
},
"runOrder": 1,
"configuration": {
"Branch": "experiment"
}
}
and finally to configuration and Branch
$ jq -r '.pipeline.stages[0].actions[0].configuration.Branch' test.json
experiment
Your json key address should be .pipeline.stages[0].actions[0].configuration.Branch so that would make your command look like this:
jq -r '.pipeline.stages[0].actions[0].configuration.Branch' test.json
That's because both stages and actions are arrays with both only a single item in them.

unix - delete a string from a json file where maching pattern

I have these data in my json file:
{
"software": [{
"softwareId": "61426b91-0403-4e72-8bc3-bee6e4aabf00",
"softwareURL": "https://mydns/download/test.json",
"softwareName": "file1",
"softwareVersion": "1.0.0",
"softwareType": "FILE",
"signature": "yTzilsyq+0qVuioDD8cNT8zAtKt+qGTJ9aQ=="
}, {
"softwareId": "716a259b-c90b-47c8-856a-25e6bca61bc8",
"softwareURL": "https://mydns/download/test1.json",
"softwareName": "file2",
"softwareVersion": "2.0.0",
"softwareType": "FILE",
"signature": "vjmTQXgCxsw/q7Wz3a4g6N5Ht+Bhumo1acw=="
}, {
"softwareId": "c72644d5-6024-4783-a520-20bf39c8ea18",
"softwareURL": "https://mydns/download/test2.json",
"softwareName": "folder",
"softwareVersion": "1.0.0",
"softwareType": "FOLDER",
"signature": "hb35vQdVuhL7pRvRmV1OdGXYFLcpC4UKn0w=="
}
]
}
I want delete the json structure {} where "softwareType": "FILE" and "softwareName": "file2".
This should be the result:
{
"software": [{
"softwareId": "61426b91-0403-4e72-8bc3-bee6e4aabf00",
"softwareURL": "https://mydns/download/test.json",
"softwareName": "file1",
"softwareVersion": "1.0.0",
"softwareType": "FILE",
"signature": "yTzilsyq+0qVuioDD8cNT8zAtKt+qGTJ9aQ=="
}, {
"softwareId": "c72644d5-6024-4783-a520-20bf39c8ea18",
"softwareURL": "https://mydns/download/test2.json",
"softwareName": "folder",
"softwareVersion": "1.0.0",
"softwareType": "FOLDER",
"signature": "hb35vQdVuhL7pRvRmV1OdGXYFLcpC4UKn0w=="
}
]
}
Could you help me to do that with a sed command or like this?
Thanks in advance.
Theres an easy way to do this using jq, and it has been answered before: Delete json array elements based on values of subarray
Using jq:
jq '.software[] | select(.softwareType!="FILE" or .softwareName!="file2")' file.json
Use select to find where the softwareType is not "FILE" or softwareName is not "file2"

storing json output in bash from cloudfromation

I am using aws ecs query to get list of properties being used by the current running task.
command -
cft = "aws ecs describe-tasks --cluster arn:aws:ecs:us-west-2:4984314772:cluster/secrets --tasks arn:aws:ecs:us-west-2:4984314772:task/secrets/86855757eec4487f9d4475a1f7c4cb0b
I am storing this in an output variable
output= $( eval $cft)
Output:
"tasks": [
{
"attachments": [
{
"id": "da8a1312-8278-46d5-8e3b-6b6a1d96f820",
"type": "ElasticNetworkInterface",
"status": "ATTACHED",
"details": [
{
"name": "subnetId",
"value": "subnet-0a151f2eb959ad4"
},
{
"name": "networkInterfaceId",
"value": "eni-081948e3666253f"
},
{
"name": "macAddress",
"value": "02:2a:9i:5c:4a:77"
},
{
"name": "privateDnsName",
"value": "ip-172-56-17-177.us-west-2.compute.internal"
},
{
"name": "privateIPv4Address",
"value": "172.56.17.177"
}
]
}
],
"availabilityZone": "us-west-2a",
"clusterArn": "arn:aws:ecs:us-west-2:4984314772:cluster/secrets",
"containers": [
{
"taskArn": "arn:aws:ecs:us-west-2:4984314772:task/secrets/86855757eec4487f9d4475a1f7c4cb0b",
"name": "nginx",
"image": "nginx",
"lastStatus": "PENDING",
"networkInterfaces": [
{
"attachmentId": "da8a1312-8278-46d5-6b6a1d96f820",
"privateIpv4Address": "172.31.17.176"
}
],
"healthStatus": "UNKNOWN",
"cpu": "0"
}
],
"cpu": "256",
"createdAt": "2020-12-10T18:00:16.320000+05:30",
"desiredStatus": "RUNNING",
"group": "family:nginx",
"healthStatus": "UNKNOWN",
"lastStatus": "PENDING",
"launchType": "FARGATE",
"memory": "512",
"overrides": {
"containerOverrides": [
{
"name": "nginx"
}
],
"inferenceAcceleratorOverrides": []
},
"platformVersion": "1.4.0",
"tags": [],
"taskArn": "arn:aws:ecs:us-west-2:4984314772:task/secrets/86855757eec4487f9d4475a1f7c4cb0b",
"taskDefinitionArn": "arn:aws:ecs:us-west-2:4984314772:task-definition/nginx:17",
"version": 2
}
],
"failures": []
}
now if do an echo of $output.tasks[0].containers[0] nothing happens it prints the entire thing again, i want to store the result in output variable and refer different parameter like we do in json format.
You will need to use a json parser such as jq and so:
eval $cft | jq '.tasks[].containers[]'
To avoid using eval you could simple pipe the aws command into jq and so:
aws ecs describe-tasks --cluster arn:aws:ecs:us-west-2:4984314772:cluster/secrets --tasks arn:aws:ecs:us-west-2:4984314772:task/secrets/86855757eec4487f9d4475a1f7c4cb0b | jq '.tasks[].containers[]'
or:
cft=$(aws ecs describe-tasks --cluster arn:aws:ecs:us-west-2:4984314772:cluster/secrets --tasks arn:aws:ecs:us-west-2:4984314772:task/secrets/86855757eec4487f9d4475a1f7c4cb0b | jq '.tasks[].containers[]')
echo $cft | jq '.tasks[].containers[]'

Nest array into new object with JQ

I know this one should be easy but it has me stumped. I am looking to take the following json example:
[{
"Name": "Test1",
"Version": "5.0.1",
"source": "source"
},
{
"Name": "Test2",
"Version": "2.0.11",
"source": "source"
},
{
"Name": "Test3",
"Version": "2.1.2",
"source": "source"
}]
and convert it to:
{
"packages": [
{
"Name": "Test1",
"Version": "5.0.1",
"source": "source"
},
{
"Name": "Test2",
"Version": "2.0.11",
"source": "source"
},
{
"Name": "Test3",
"Version": "2.1.2",
"source": "source"
}
]
}
I've tried numerous different ways, the closest I got is using something similar to: jq '.packages += [input]'
Basically it's just moving the original JSON to be nested. Any help would be appreciated.
just do this
jq '{ packages : . }' input.json
Even things you think of as literals are really filters in jq. The filter you need in this case is simply {packages: .}:
$ echo '[{}, {}]' | jq '{packages: .}'
{
"packages": [
{},
{}
]
}

Query parent data (multi-level) based on a child value, on a json file, using jq

I have a ksh script that retrives (using curl) a json file similar to the one bellow:
{
"Type1": {
"dev": {
"server": [
{ "group": "APP1", "name": "DAPP1002", "ip": "10.1.1.1" },
{ "group": "APP2", "name": "DAPP2001", "ip": "10.1.1.2" }
]
},
"qa": {
"server": [
{ "group": "APP1", "name": "QAPP1002", "ip": "10.1.2.1" },
{ "group": "APP2", "name": "QAPP2001", "ip": "10.1.2.2" }
]
},
"prod": {
"proxy": "type1.prod.proxy.mydomain.com",
"server": [
{ "group": "APP1", "name": "PAPP1001", "ip": "10.1.3.1" },
{ "group": "APP1", "name": "PAPP1002", "ip": "10.1.3.2" },
{ "group": "APP2", "name": "PAPP2001", "ip": "10.1.3.3" }
]
}
},
"Type2": {
"dev": {
"server": [
{ "group": "APP8", "name": "DAPP8002", "ip": "10.2.1.1" },
{ "group": "APP9", "name": "DAPP9001", "ip": "10.2.1.2" }
]
},
"qa": {
"server": [
{ "group": "APP8", "name": "QAPP8002", "ip": "10.2.2.1" },
{ "group": "APP9", "name": "QAPP9001", "ip": "10.2.2.2" }
]
},
"prod": {
"proxy": "type2.prod.proxy.mydomain.com",
"server": [
{ "group": "APP8", "name": "PAPP8001", "ip": "10.2.3.1" },
{ "group": "APP9", "name": "PAPP9001", "ip": "10.2.3.2" },
{ "group": "APP9", "name": "PAPP9002", "ip": "10.2.3.3" }
]
}
}
}
... based on a server name (field "name") I would have to collect the following info, to pass to a function:
"Type", "name", "ip", "proxy"
(Note that the "proxy" info is optional)
I am new to json, and I am trying to get this filtered with jq but so far, I am out of lucky.
What I acomplished so far is the following jq query, when searching for "PAPP9001" :
jq '.[] | .[] | select(.server[].name=="PAPP9001") | .proxy as $proxy | .server[] | {proxy: $proxy, name: .name, ip: .ip} | select(.name=="PAPP9001")' curlreturn.json
which returns me:
{
"proxy": "type2.prod.proxy.mydomain.com",
"name": "PAPP9001",
"ip": "10.2.3.2"
}
but:
I could not get the "Type" info, at the top level
Considering the number of pipes and the 2 selects, I doubt that this is the most efficient way.
One way to retrieve the key names programmatically is using to_entries. For example, given your input, this jq filter:
to_entries[]
| .key as $type
| .value[]
| .proxy as $proxy
| .server[]
| select(.name == "PAPP9001")
| { Type: $type, name, ip, proxy: $proxy }
yields:
{
"Type": "Type2",
"name": "PAPP9001",
"ip": "10.2.3.2",
"proxy": "type2.prod.proxy.mydomain.com"
}
Variations
If, for example, you wanted these four fields as a CSV row, then you could replace the last line of the filter above with:
| [$type, .name, .ip, $proxy] | #csv
See the jq manual for how to use string interpolation.