JQ Not Taking In Variable Data - json

I am unsuccessfully trying to add variable data to a json within a ci script. I am attempting to use the --arg VariableName VariableData notation.
For example purposes, I am only passing $date which has already been set earlier in the script. In the outputted JSON, the literal string $date is outputted instead of the variable.
jq --arg date "$date" '.sections[0].builds += [{"title": "Version MyVersion", "timestamp": "$date", "iOS": "My_URL.plist" }]' builds.json > builds1.json
This results in:
{
"title": "MY Title",
"columnCount": 1,
"notes_OFF": "First_Test",
"sections": [
{
"title": "My Title",
"builds": [
{
"title": "Version MyVersion",
"timestamp": "$date",
"iOS": "My_URL.plist"
}
]
}
]
}
Original JSON:
{
"title": "MY Title",
"columnCount": 1,
"notes_OFF": "First_Test",
"sections": [
{
"title": "My Title",
"builds": [
]
}
]
}
What am I doing wrong here?

Replace "$date" with $date in your filter.

Related

How do I pass variables through a Json body Powershell

I want to pass variables in for these values but I cant get them to go for example in user_id I want to pass the variable $userID
This is an example of the Body i'm using:
$body = '{
"data":
[
{
"user_id":$userID,
"type":"manual",
"date":"2021-01-30",
"duration":"150",
"jobcode_id":"15281216",
"notes":"This is a test of a manual time entry",
"customfields": {
"54138" : "IT Services",
"54136" : "Yes"
}
}
]
}'
I would use a double-quoted Here-String for that:
$userID = 'Alex'
$body = #"
{
"data": [{
"user_id": "$userID",
"type": "manual",
"date": "2021-01-30",
"duration": "150",
"jobcode_id": "15281216",
"notes": "This is a test of a manual time entry",
"customfields": {
"54138": "IT Services",
"54136": "Yes"
}
}]
}
"#
$body now contains:
{
"data": [{
"user_id": "Alex",
"type": "manual",
"date": "2021-01-30",
"duration": "150",
"jobcode_id": "15281216",
"notes": "This is a test of a manual time entry",
"customfields": {
"54138": "IT Services",
"54136": "Yes"
}
}]
}
The reason why $userID is not substituted for it's value in your example is because you are using a single quote (') character. PowerShell only substitutes when you use a double quote (") character.
This would give you the challenge that your data already contains double quotes. There Here string from Theo's answers works just fine but as a personal preference I would use a PowerShell hashtable to construct an object and convert it to Json using Convert-To-Json.
Example:
$userID = 'John'
$body = #{
"data" = ,#{
"user_id" = $userID;
"type" = "manual";
"date" = "2021-01-30";
"duration" = "150";
"jobcode_id" = "15281216";
"notes" = "This is a test of a manual time entry";
"customfield" = #{
"54138" = "IT Services";
"54136" = "Yes";
}
}
}
$body | ConvertTo-Json -Depth 3
Output:
{
"data": [
{
"notes": "This is a test of a manual time entry",
"customfield": {
"54138": "IT Services",
"54136": "Yes"
},
"duration": "150",
"type": "manual",
"date": "2021-01-30",
"jobcode_id": "15281216",
"user_id": "John"
}
]
}
EDIT: As robdy mentioned in the comments, the Depth parameter should be used (I've added it). A good explanation can be found here.

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.

Using jq find key/value pair based on another key/value pair

I'm pasting here a JSON example data which would require some manipulation to get a desired output which is mentioned in the next section to be read after this piece of JSON code.
I want to use jq for parsing my desired data.
{
"MetricAlarms": [
{
"EvaluationPeriods": 3,
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
"AlarmActions": [
"Unimportant:Random:alarm:ELK2[10.1.1.2]-Root-Disk-Alert"
],
"AlarmName": "Unimportant:Random:alarm:ELK1[10.1.1.0]-Root-Alert",
"Dimensions": [
{
"Name": "path",
"Value": "/"
},
{
"Name": "InstanceType",
"Value": "m5.2xlarge"
},
{
"Name": "fstype",
"Value": "ext4"
}
],
"DatapointsToAlarm": 3,
"MetricName": "disk_used_percent"
},
{
"EvaluationPeriods": 3,
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
"AlarmActions": [
"Unimportant:Random:alarm:ELK2[10.1.1.2]"
],
"AlarmName": "Unimportant:Random:alarm:ELK2[10.1.1.2]",
"Dimensions": [
{
"Name": "path",
"Value": "/"
},
{
"Name": "InstanceType",
"Value": "r5.2xlarge"
},
{
"Name": "fstype",
"Value": "ext4"
}
],
"DatapointsToAlarm": 3,
"MetricName": "disk_used_percent"
}
]
}
So when I Pass some Key1 & value1 as a parameter "Name": "InstanceType", to the JQ probably using cat | jq and output expected should be as below
m5.2xlarge
r5.2xlarge
A generic approach to search for a key-value pair (sk-sv) in input recursively and extract another key's value (pv) from objects found:
jq -r --arg sk Name \
--arg sv InstanceType \
--arg pv Value \
'.. | objects | select(contains({($sk): $sv})) | .[$pv]' file

Add or Update a field in one JSON file from another JSON file based on matching field

I have two JSON files a.json and b.json. The contents in a.json file is a JSON object and inside b.json its an array.I want to add/update status field in each mappings in a.json by retrieving the value from b.json file.
a.json:
{
"title": 25886,
"data": {
"request": {
"c": 46369,
"t1": 1562050127.376641
},
},
"rs": {
"mappings": {
"12345": {
"id": "12345",
"name": "test",
"customer_id": "11228",
},
"45678": {
"id": "45678",
"name": "abc",
"customer_id": "11206",
}
}
}}
b.json:
[
{
"status": "pending",
"extra": {
"name": "test"
},
"enabled": true,
"id": "12345"
},
{
"status": "not_started",
"extra": {
"name": "abc"
},
"enabled": true,
"id": "45678"
}
]
Below is my expected output:
{
"title": 25886,
"data": {
"request": {
"c": 46369,
"t1": 1562050127.376641
},
},
"rs": {
"mappings": {
"12345": {
"id": "12345",
"name": "test",
"customer_id": "11228",
"status":"pending"
},
"45678": {
"id": "45678",
"name": "abc",
"customer_id": "11206",
"status":"not_started"
}
}
}}
In this expected JSON file we have status field whose value is retrieved from b.json file based on a matching id value. How to do this using jq ?
For the purposes of this problem, b.json essentially defines a dictionary, so for simplicity, efficiency and perhaps elegance,
it make sense to start by using the builtin function INDEX to create the relevant dictionary:
INDEX( $b[] | {id, status}; .id )
This assumes an invocation of jq along the lines of:
jq --argfile b b.json -f update.jq a.json
(Yes, I know --argfile has been deprecated. Feel free to choose another way to set $b to the contents of b.json.)
Now, to perform the update, it will be simplest to use the "update" operator, |=, in conjunction with map_values. (Feel free to check the jq manual :-)
Putting everything together:
INDEX( $b[] | {id, status}; .id ) as $dict
| .rs.mappings |= map_values( .status = $dict[.id].status )

Add a new key/value to every object in json array in file with jq

I have a json file like below. I want to add "stable": "yes" to every object in this file with jq. How can i do this?
[
{
"id":"1",
"name":"Blue"
},
{
"id":"2",
"name":"Red"
}
]
I want it to be like this:
[
{
"id":"1",
"name":"Blue",
"stable": "yes"
},
{
"id":"2",
"name":"Red",
"stable": "yes"
}
]
map and + will do this:
$ jq 'map(. + {stable: "yes"})' tmp.json
[
{
"id": "1",
"name": "Blue",
"stable": "yes"
},
{
"id": "2",
"name": "Red",
"stable": "yes"
}
]
Since the input is an array, the . refers to each object in that array, to which we add another object.
Note this will also override any existing stable key in each object.