JSON QUERY parse tip - json

just want to get some expert tips on you on how to grab only this from AutoScalingGroups:
awseb-e-ASG
Actual JSON Output
{
"EnvironmentResources": {
"EnvironmentName": "MY-APP",
"AutoScalingGroups": [
{
"Name": "awseb-e-ASG"
}
],
"Triggers": [],
"LoadBalancers": [
{
"Name": "awseb-e-ELB"
}
],
"Queues": [],
"Instances": [
{
"Id": "i-XXXXXXXXXXXXXXXd"
}
],
"LaunchConfigurations": [
{
"Name": "awseb-e-LAUNCH"
}
]
}
}
I tried several commands but only getting this:
jq -r ".EnvironmentResources.LaunchConfigurations"
[
{
"Name": "awseb-e-ASG"
}
]
jq -r ".EnvironmentResources.LaunchConfigurations.Name"
jq: error: Cannot index array with string

awseb-e-ASG is under .AutoScalingGroups
so you could use the following filter:
.EnvironmentResources.AutoScalingGroups[].Name
Debugging
It usually pays to pay attention to the error message:
jq: error: Cannot index array with string
This, in effect, is telling you that .LaunchConfigurations.Name is erroneous because .LaunchConfigurations is an array, and therefore cannot have a string-valued key.

Related

How to check if json contains another json using jq?

I have just started using jq and I need to check if a given json is present in another json using jq?
Suppose this is my json_input:
{
"info": {
"values": [
{
"data": [
{
"name": "name",
"value": "val"
}
]
}
]
}
}
I need to check if the above json input is present inside the following available_json:
{
"info": {
"values": [
{
"data": [
{
"name": "name",
"value": "val"
},
{
"name": "name2",
"value": "val2"
},
{
"name": "name3",
"value": "val3"
}
],
"key1":"val1",
"key2":"val2"
}
],
"priority":1,
"objects":[
{
"name":"a"}
]
}
}
Both json are stored in variables and should report the presence for any json_input given as input based on any available_json (generic). How can this be done using jq?
Or Is there any other better way like converting both json to string and then comparing?
PS: The json object key info is fixed and the values can change.
This is so trivial that one might not even think of it: Using the jq filter contains:
jq 'contains({
"info": {
"values": [
{
"data": [
{
"name": "name",
"value": "val"
}
]
}
]
}
})' available.json
Output will be true or false. If you run jq -e (--exit-status), it will set the exit status accordingly, which allows you to use it together with if or &&/|| in your shell.
If you the input_json is also stored in a file:
jq --slurpfile input_json input_json 'contains($input_json[0])' available.json
If the JSON document is stored in a variable, then --argjson instead of --slurpfile:
jq --argjson input_json "$input_json" 'contains($input_json)' available.json
or simply relying on parameter expansion of your shell:
jq "contains($input_json)" available.json

JQ get data from an array of array

How can I get a value from an array of arrays. This is JSON from which I have to get the data:
{
"status": "success",
"data": {
"resultType": "matrix",
"result": [
{
"metric": {
"myMetric": "ABC"
},
"values": [
[
1633597734,
"64.54166666666667"
],
[
1633598034,
"65.51666666666667" <-- wanted value
]
]
}
]
}
}
I have to get value from the last array in values.
I tried the following:
jq .data.result.values input.json
jq .data.result.values[] input.json
jq .data.result.values[][] input.json
For every one the result is:
jq: error (at json:0): Cannot index array with string "values"
How can I get value from the last array in values?
You can use a negative index to enumerate from the back of an array: to get the last element of the last array in the values of the last element of result:
.data.result[-1].values[-1][-1]
demo: https://jqplay.org/s/YMpB8-A4-Q
filter:
.data.result[].values[1][1]?
input:
{
"status": "success",
"data": {
"resultType": "matrix",
"result": [
{
"metric": {
"myMetric": "ABC"
},
"values": [
[
1633597734,
"64.54166666666667"
],
[
1633598034,
"65.51666666666667"
]
]
}
]
}
}
output:
"65.51666666666667"

Creating a new element in an json object using jq

Is there a way to create a new element in an existing json object using jq? Example below:
Let's say I have this json object and would like to add a new element to foo:
json='{
"id": "<id>>",
"name": "<name>",
"properties": {
"State": "<state>",
"requests": [],
"foo": [
{
"id": "<id1>",
"bar1": [
{
"baz1": "*"
}
]
},
{
"id": "<id2>",
"bar2": [
{
"baz2": "*"
}
]
}
]
}
}'
This command works to do that:
json2=$($json1 | jq '.properties.foo += [ { "id": "<id3>", "bar3": [ { "baz3": "*"} ] } ]')
However, running that same command without a preexisting foo element fails (example array below):
json3='{
"id": "<id>>",
"name": "<name>",
"properties": {
"State": "<state>",
"requests": []
}
}'
Is there a way in jq to create that element in the json object if one already does not exist?
Thanks!
There is nothing wrong with your jq program, which can be seen by running:
jq '.properties.foo += [ { "id": "<id3>", "bar3": [ { "baz3": "*"} ] } ]' <<< "$json3"
It looks like the problem is with your invocation but since it's not clear what $json1 is, I'll just guess that the above is sufficient for you to resolve the issue.

How to delete array elements that end with 1?

I need to remove all array elements that have the name field ending with 1.
Input:
{
"foo": "bar",
"data": {
"code": "abc123",
"items": [
{
"name": "exp1"
},
{
"name": "exp2"
},
{
"name": "exp11"
}
]
}
}
Desired output:
{
"foo": "bar",
"data": {
"code": "abc123",
"items": [
{
"name": "exp2"
}
]
}
}
My attempt:
jq 'del(.data.items[] | select(.name | endswith("1")))' input
Which results in Invalid path expression.
You can use this jq filter:
jq '.data.items|=map(select(.name|endswith("1")|not))' file
This replace .data.items with the a new array having objects whose names don't end with 1.
Your attempt will work with recent versions of jq (that is, more recent than version 1.5).
Yet another variant (perhaps the most concise robust alternative):
.data.items|=map(select(.name|test("[^1]$")))

Create one JSON from another, with extra data va JQ

I have this file:
[
"smoke-tests",
"push-apps-manager"
]
I'd like to get this output using JQ:
{
"errands": [
{"name": "smoke-tests", "post_deploy": true},
{"name": "push-apps-manager", "post_deploy": true}
]
}
It seems so simple, yet, I have so much difficulty here...
It's a little tricky, since you need to embed the input into the list bound to the errands key. Start by creating the sequence of name/post_deploy objects:
% jq '.[] | {name: ., post_deploy: true}' names.json
{
"name": "smoke-tests",
"post_deploy": true
}
{
"name": "push-apps-manager",
"post_deploy": true
}
Then wrap that in the list in the outer object:
% jq '{errands: [.[] | {name: ., post_deploy: true}]}' names.json
{
"errands": [
{
"name": "smoke-tests",
"post_deploy": true
},
{
"name": "push-apps-manager",
"post_deploy": true
}
]
}
You can also use the map function (which I rarely remember how to use correctly, but it turns out is pretty simple here):
% jq '{errands: map({name:., post_deploy: true})}' names.json
Here is another approach. If you are new to jq it may be easiest to work towards the goal in small steps.
1) Start with the identity filter
.
which produces as expected
[
"smoke-tests",
"push-apps-manager"
]
2) next add the outer object with the "errands" key:
{ "errands": . }
which produces
{
"errands": [
"smoke-tests",
"push-apps-manager"
]
}
3) next move the data into an array
{ "errands": [ . ] }
which produces
{
"errands": [
[
"smoke-tests",
"push-apps-manager"
]
]
}
4) add the inner object with the "name" and "post_deploy" keys
{ "errands": [ { "name": ., "post_deploy": true } ] }
which produces
{
"errands": [
{
"name": [
"smoke-tests",
"push-apps-manager"
],
"post_deploy": true
}
]
}
5) Now we're really close. All we need to do is take advantage of jq's Object Construction behavior when an expression produces multiple results :
{ "errands": [ { "name": .[], "post_deploy": true } ] }
which gives us the desired result
{
"errands": [
{
"name": "smoke-tests",
"post_deploy": true
},
{
"name": "push-apps-manager",
"post_deploy": true
}
]
}