Extract JSON including key with jq command - json

HERE is sample json file.
sample.json
{
"apps": [
{
"name": "app1"
},
{
"name": "app2"
},
{
"name": "app3"
}
],
"test": [
{
"name": "test1"
},
{
"name": "test2"
}
]
}
I want to divide the above JSON file into the following two files.
I want to manage the entire configuration file with one JSON, divide the file when necessary and give it to the tool.
apps.json
{
"apps": [
{
"name": "app1"
},
{
"name": "app2"
},
{
"name": "app3"
}
}
test.json
{
"test": [
{
"name": "test1"
},
{
"name": "test1"
}
]
}
jq .apps sample.json outputs only value.
[
// Not contain the key
{
"name": "app1"
},
{
"name": "app2"
},
{
"name": "app3"
}
]
Can you have any idea?

Construct a new object using {x} which is a shorthand for {x: .x}.
jq '{apps}' sample.json
{
"apps": [
{
"name": "app1"
},
{
"name": "app2"
},
{
"name": "app3"
}
]
}
Demo
And likewise with {test}.

You can do
{apps}, {test}
Demo
https://jqplay.org/s/P_9cc2uANV

Related

find and replace in json file using jq filter

I've below json file env.json and I want to search for "[\"res\",\"q3\"]" and replace it with a variable var1 value "[\"res\"]"
{
"idsb": "marqd",
"data": {
"name": "bcon-dv-alert"
},
"ingress": {
"args": {
"params": [
{
"name": "spt",
"value": "cld"
},
{
"name": "scv",
"value": "sdv"
},
{
"name": "scr",
"value": "ord"
}
{
"name": "srm",
"value": "[\"res\",\"q3\"]"
},
{
"name": "tgo",
"value": "pbc"
}
]
},
"wfr": {
"name": "t-r-e"
},
"snm": "as-r"
}
}
I tried the below way but it's not working
var1="[\"res\"]"
jq '.ingress.args.params[] | select(.name=="srm").value |= ["'${var1}'"]' env.json
where am making mistake? what's the right way to do it?
The final result will be
{
"idsb": "marqd",
"data": {
"name": "bcon-dv-alert"
},
"ingress": {
"args": {
"params": [
{
"name": "spt",
"value": "cld"
},
{
"name": "scv",
"value": "sdv"
},
{
"name": "scr",
"value": "ord"
}
{
"name": "srm",
"value": "[\"res\"]"
},
{
"name": "tgo",
"value": "pbc"
}
]
},
"wfr": {
"name": "t-r-e"
},
"snm": "as-r"
}
}
Since you want to update ingress, and not return only the result of the loops, use:
.ingress.args.params |= map(select(.name=="srm").value |= "new-value")
Try it online

How to combine 2 JSON objects into one with jq?

I have two JSON objects in two files (result_0.json and result_1.json) which look like this
{
"data": {
"pools": [
{
"id": "1"
},
{
"id": "2"
}
]
}
}
and like this:
{
"data": {
"pools": [
{
"id": "3"
},
{
"id": "4"
}
]
}
}
What I would like to get looks like this:
{
"data": {
"pools": [
{
"id": "1"
},
{
"id": "2"
},
{
"id": "3"
},
{
"id": "4"
}
]
}
}
How can it be done? I tried
jq -s add result_0.json result_1.json
but it just overwrites the values in result_0.json with the values of result_1.json.
If .data and .pool are the only keys in the json files, you can use
jq -n '{ data: { pools: [inputs.data.pools] | add } }' result0 result1
This will create the desired output:
{
"data": {
"pools": [
{
"id": "1"
},
{
"id": "2"
},
{
"id": "3"
},
{
"id": "4"
}
]
}
}
Regarding the inputs keyword, consider reading JQ's docs on this part.

Getting unique values from nested Array using jq

Trying to get unique values stored in items array for each group. somehow it's always mixed...
My JSON looks like this:
{
"start": 1534425916,
"stop": 1535030716,
"groups": [
{
"group": "transmission",
"data": {
"events": 665762,
},
"items": [
{
"item": "manualni",
"data": {
"events": 389158,
}
},
{
"item": "automaticka",
"data": {
"events": 276604,
}
}
]
},
{
"group": "vat",
"data": {
"events": 671924,
},
"items": [
{
"item": "ne",
"data": {
"events": 346221,
}
},
{
"item": "ano",
"data": {
"events": 325703,
}
}
]
}
]
}
Desired result is the following:
{
"id": "transmission",
"value": [
"manualni",
"automaticka",
]
}
{
"id": "vat",
"value": [
"ne",
"ano"
]
}
Tried with this filter on command line:
| jq '{id: .groups[].group, value: [.groups[].items[].item]}'
Which results in the above mentioned mixed up result:
{
"id": "transmission",
"value": [
"manualni",
"automaticka",
"ne",
"ano"
]
}
{
"id": "vat",
"value": [
"manualni",
"automaticka",
"ne",
"ano"
]
}
Any idea how to receive the uniquified values here? Thanks in advance!
This gets the desired result. I think the manual entry under .[] explains why it works.
jq '.groups[] | {"id": .group, "value": [.items[].item]}'

Add to existing json file using jq

I have an Artifactory AQL Spec file in JSON format. The spec file is as follows:
{
"files": [
{
"aql": {
"items.find": {
"repo": "release-repo",
"modified": { "$before": "30d" },
"type": { "$eq": "folder" },
"depth": "2"
}
}
}
]
}
let's say I run a gitlab api query to acquire a list of SHAs that I want to iterate through and add to this json spec file.. The list of SHAs are assigned to a variable..
"a991fef6bb9e9759d513fd4b277fe3674b44e4f4"
"5a562d34bb1d4ab4264acc2c61327651218524ad"
"d4e296c35644743e58aed35d1afb87e34d6c8823"
I would like to iterate through all these commit IDs in and add them one by one to the json so that they are in this format:
{
"files": [
{
"aql": {
"items.find": {
"repo": "release-repo",
"modified": { "$before": "30d" },
"type": { "$eq": "folder" },
"$or": [
{
"$and": [
{
"name": {
"$nmatch": "*a991fef6bb9e9759d513fd4b277fe3674b44e4f4*"
}
}
]
},
{
"$and": [
{
"name": {
"$nmatch": "*5a562d34bb1d4ab4264acc2c61327651218524ad*"
}
}
]
},
{
"$and": [
{
"name": {
"$nmatch": "*d4e296c35644743e58aed35d1afb87e34d6c8823*"
}
}
]
}
],
"depth": "2"
}
}
}
]
}
The list of SHAs returned from the gitlab api query will be different everything and that's why I'd like this to be a dynamic entry or update every time. The number of returned SHAs will also be different... Could return 10 one day or it could return 50 on another day.
#!/usr/bin/env bash
template='{
"files": [
{
"aql": {
"items.find": {
"repo": "release-repo",
"modified": { "$before": "30d" },
"type": { "$eq": "folder" },
"$or": [],
"depth": "2"
}
}
}
]
}'
shas=(
"a991fef6bb9e9759d513fd4b277fe3674b44e4f4"
"5a562d34bb1d4ab4264acc2c61327651218524ad"
"d4e296c35644743e58aed35d1afb87e34d6c8823"
)
jq -n \
--argjson template "$template" \
--arg shas_str "${shas[*]}" \
'
reduce ($shas_str | split(" ") | .[]) as $sha ($template;
.files[0].aql["items.find"]["$or"] += [{
"$and": [{"name": {"$nmatch": ("*" + $sha + "*")}}]
}]
)
'
...emits as output:
{
"files": [
{
"aql": {
"items.find": {
"repo": "release-repo",
"modified": {
"$before": "30d"
},
"type": {
"$eq": "folder"
},
"$or": [
{
"$and": [
{
"name": {
"$nmatch": "*a991fef6bb9e9759d513fd4b277fe3674b44e4f4*"
}
}
]
},
{
"$and": [
{
"name": {
"$nmatch": "*5a562d34bb1d4ab4264acc2c61327651218524ad*"
}
}
]
},
{
"$and": [
{
"name": {
"$nmatch": "*d4e296c35644743e58aed35d1afb87e34d6c8823*"
}
}
]
}
],
"depth": "2"
}
}
}
]
}
Here is a reduce-free solution. It makes some inessential assumptions -
that the sha strings are presented as a stream of strings on STDIN, and that the Artifactory spec is in a file named spec.json. Here is the jq program:
map( {"$and": [ {name: { "$nmatch": "*\(.)*" }}]} ) as $x
| $spec[0] | (.files[0].aql."items.find"."$or" = $x)
The jq invocation might look like this:
jq -s --slurpfile spec spec.json -f program.jq <<< "${shas[*]}"

merging 2 json into one single json with value parsing in bash.

I have two JSONS:
{
"name": "paypal_modmon",
"description": "Role For Paypal admin-service box",
"run_list": [
"recipe[djcm_paypal_win::sslVerify]"
]
}
and
{
"name": "paypal_dev",
"default_attributes": {
"7-zip": {
"home": "%SYSTEMDRIVE%\\7-zip"
},
"modmon": {
"env": "dev"
},
"paypal": {
"artifact": "%5BINTEGRATION%5D"
}
},
"override_attributes": {
"default": {
"env": "developmen"
},
"windows": {
"password": "Pib1StheK1N5"
},
"task_sched":{
"credentials": "kX?rLQ4XN$q"
},
"seven_zip": {
"url": "https://djcm:Pib1StheK1N5#artifactory.dowjones.io/artifactory/djcm-zip-local/djcm/chef/paypal/7z1514-x64.msi"
}
},
"chef_type": "environment"
}
I want to read the values from the second json : "default_attributes" and "override_attributes" and merge them with the first json into an output like :
{
"description": "Role For Paypal admin-service box",
"run_list": [
"recipe[djcm_paypal_win::sslVerify]"
],
"chef_type": "environment",
"seven_zip": {
"url": "https://djcm:Pib1StheK1N5#artifactory.dowjones.io/artifactory/djcm-zip-local/djcm/chef/paypal/7z1514-x64.msi"
},
"task_sched": {
"credentials": "kX?rLQ4XN$q"
},
"windows": {
"password": "Pib1StheK1N5"
},
"paypal": {
"artifact": "%5BINTEGRATION%5D"
},
"modmon": {
"env": "dev"
},
"7-zip": {
"home": "%SYSTEMDRIVE%\\7-zip"
},
"default": {
"env": "developmen"
},
"name": "paypal_modmon"
}
Is there a way to do this in bash and how would go to achieve it ?
Generally, if you're reading in multiple files, you should use the --argfile option so you can reference the contents of the file by name. And judging by the name of the attributes you wish to merge, you should be wary of the different merging options you have. default_attributes suggests it should be attributes that should be used if omitted. override_attributes suggests it should force it's values in.
$ jq --argfile merge input2.json \
'($merge.default_attributes * .) + $merge.override_attributes' input1.json
By merging the input with the default_attributes using *, it allows you to start with the defaults and add your actual values in place. That way missing values end up being provided by the default object.
Then adding the override_attributes object, the values are completely replaced and not just merged.
Got it. With jq seems super simple :
jq -s '.[0] + .[1].default_attributes + .[1].override_attributes' a-roles.json a-env.json > manifest.json
manifest.json ->
{
"default": {
"env": "developmen-jq"
},
"7-zip": {
"home": "%SYSTEMDRIVE%\\7-zip"
},
"name": "paypal_modmon",
"description": "Role For Paypal admin-service box",
"run_list": [
"recipe[djcm_paypal_win::sslVerify]"
],
"seven_zip": {
"url": "https://djcm:Pib1StheK1N5#artifactory.dowjones.io/artifactory/djcm-zip-local/djcm/chef/paypal/7z1514-x64.msi"
},
"task_sched": {
"credentials": "kX?rLQ4XN$q"
},
"windows": {
"password": "Pib1StheK1N5"
},
"paypal": {
"artifact": "%5BINTEGRATION%5D"
},
"modmon": {
"env": "dev"
}
}
EDIT 1 :
I also need to parse out the run_list key value pair from a-roles.json and ignore all other info to have something:
{
"default": {
"env": "developmen-jq"
},
"7-zip": {
"home": "%SYSTEMDRIVE%\\7-zip"
},
"run_list": [
"recipe[djcm_paypal_win::sslVerify]"
],
"seven_zip": {
"url": "https://djcm:Pib1StheK1N5#artifactory.dowjones.io/artifactory/djcm-zip-local/djcm/chef/paypal/7z1514-x64.msi"
},
"task_sched": {
"credentials": "kX?rLQ4XN$q"
},
"windows": {
"password": "Pib1StheK1N5"
},
"paypal": {
"artifact": "%5BINTEGRATION%5D"
},
"modmon": {
"env": "dev"
}
}
is that possible with jq ?