Add JSON object to JSON file using JQ - json

Given the following JSON file (sample.json)
{
"api": "3.0.0",
"data": {
"description": "something",
"title": "hello",
"version": "1.0",
"app": {
"name": "abc",
"id": "xyz"
}
}
}
I wish to add the following JSON object at root level to the file above:
{
"heading": {
"user": ["$username"]
}
}
Where $username is a Bash variable.
Is there a better way to achieve this than the following?
blob=$(jq -n --arg foo API_NAME '{"heading": {"user": [env.username]}}')
jq --argjson obj "$(echo $blob)" '. + $obj' < sample.json

Just move what you create as blob directly into the other filter, ending up with just one jq call:
jq --arg username "$username" '. + {heading: {user: [$username]}}' sample.json

Related

Transform JSON array to object with jq

I'm trying to transform array to object by specific key. It works fine without using stream, but not possible when stream is applied.
Data:
[
{
"id": "1",
"userId": "fa51531d"
}
,
{
"id": "2",
"userId": "a167869a"
}
]
I tried running this command but it throws an error.
jq -n --stream 'fromstream(1|truncate_stream(inputs)) | INDEX(.id)' test.json > result.json
Data above should be transformed to:
{
"1": {
"userId": "fa51531d",
"id": "1"
},
"2": {
"userId": "a167869a",
"id": "2"
},
}
I want to achieve the same result as with jq 'INDEX(.id) but I need to use stream (because of big JSON file).
If you are trying to recreate the whole input object, the stream-based approach is rendered pointless. That said, using this approach, there's no need to truncate. So either replace 1 with 0:
jq -n --stream 'fromstream(0|truncate_stream(inputs)) | INDEX(.id)'
Or just omit it entirely (which reveals its futility):
jq -n --stream 'fromstream(inputs) | INDEX(.id)'
What would make more sense, is to output a stream of objects, each indexed as with INDEX. Maybe you were looking for this:
jq -n --stream 'fromstream(1|truncate_stream(inputs)) | {(.id):.}'
{
"1": {
"id": "1",
"userId": "fa51531d"
}
}
{
"2": {
"id": "2",
"userId": "a167869a"
}
}
To transform your JSON Array to JSON Object maybe you can use this
jq reduce .[] as $item ({}; .[$item.id] = $item)
but if you want to stream the JSON, i don't have the solutions
cmiiw
If your stream really looks like in your question, this should do:
jq 'INDEX(.id)' test.json
Output:
{
"1": {
"id": "1",
"userId": "fa51531d"
},
"2": {
"id": "2",
"userId": "a167869a"
}
}

replace json node with another json file with command line jq

I have a result.json:
{
"Msg": "This is output",
"output": {}
}
and a output.json:
{
"type": "string",
"value": "result is here"
}
I want to replace output field in result.json with whole file output.json as
{
"Msg": "This is output",
"output": {
"type": "string",
"value": "result is here"
}
}
and idea with jq command line? Thank you in advance.
You can use --argfile to process multiple files :
jq --argfile f1 result.json --argfile f2 output.json -n '$f1 | .output = $f2'
Basically the same as Bertrand Martel's answer, but using a different (and shorter) approach to reading the two files.
jq -n 'input | .output = input' result.json output.json

json array into json stream with jq

This task is similar to this one but in my case I would like to go other way around.
So say we have input:
[
{
"name": "John",
"email": "john#company.com"
},
{
"name": "Brad",
"email": "brad#company.com"
}
]
and desired output is:
{
"name": "John",
"email": "john#company.com"
}
{
"name": "Brad",
"email": "brad#company.com"
}
I tried to write a bash function which will do it in loop:
#!/bin/bash
json=`cat $1`
length=`echo $json | jq '. | length'`
for (( i=0; i<$length ; i++ ))
do
echo $json | jq ".[$i]"
done
but it is obviously extremly slow...
Is there any way how to use jq better for this?
You can use this :
jq '.[]' file
If you use the .[index] syntax, but omit the index entirely, it will return all of the elements of an array.
Test:
$ jq '.[]' file
{
"email": "john#company.com",
"name": "John"
}
{
"email": "brad#company.com",
"name": "Brad"
}
you can apply ".[]" filter.
This tutorial is very informative
https://stedolan.github.io/jq/tutorial/

json jq add same element to each object/array

I have files with json structure like this:
[
{
"uid": 11111,
"something": {
(...)
}
},
{
"uid": 22222,
"something": {
(...)
}
}
]
I'll read all files at one time (cat *) and i'd like to know which part is from which file, so i need to group it in some way.
So, my idea is to move content of each file to higher (parent) object with own members.
[
{
"var1": "val1"
"var2": "val2"
{
"uid": 11111,
"something": {
(...)
}
},
{
"uid": 22222,
"something": {
(...)
}
}
}
How to do that with jq?
#!/bin/bash
# For simplicity, assume each file in FILELIST contains a single JSON entity.
# Then instead of using cat FILELIST, use mycat FILELIST, e.g. mycat *.json
function mycat {
for file
do
jq --arg file "$file" '{"file": $file, "contents": .}' "$file"
done
}
If you have a sufficiently recent version of jq (e.g. jq 1.5) then one alternative would be:
jq '{file: input_filename, contents: .}' FILELIST

Update inner attribute of JSON with jq

Could somebody help me to deal with jq command line utility to update JSON object's inner value?
I want to alter object interpreterSettings.2B263G4Z1.properties by adding several key-values, like "spark.executor.instances": "16".
So far I only managed to fully replace this object, not add new properties with command:
cat test.json | jq ".interpreterSettings.\"2B188AQ5T\".properties |= { \"spark.executor.instances\": \"16\" }"
This is input JSON:
{
"interpreterSettings": {
"2B263G4Z1": {
"id": "2B263G4Z1",
"name": "sh",
"group": "sh",
"properties": {}
},
"2B188AQ5T": {
"id": "2B188AQ5T",
"name": "spark",
"group": "spark",
"properties": {
"spark.cores.max": "",
"spark.yarn.jar": "",
"master": "yarn-client",
"zeppelin.spark.maxResult": "1000",
"zeppelin.dep.localrepo": "local-repo",
"spark.app.name": "Zeppelin",
"spark.executor.memory": "2560M",
"zeppelin.spark.useHiveContext": "true",
"spark.home": "/usr/lib/spark",
"zeppelin.spark.concurrentSQL": "false",
"args": "",
"zeppelin.pyspark.python": "python"
}
}
},
"interpreterBindings": {
"2AXUMXYK4": [
"2B188AQ5T",
"2AY8SDMRU"
]
}
}
I also tried the following but this only prints contents of interpreterSettings.2B263G4Z1.properties, not full object.
cat test.json | jq ".interpreterSettings.\"2B188AQ5T\".properties + { \"spark.executor.instances\": \"16\" }"
The following works using jq 1.4 or jq 1.5 with a Mac/Linux shell:
jq '.interpreterSettings."2B188AQ5T".properties."spark.executor.instances" = "16" ' test.json
If you have trouble adapting the above for Windows, I'd suggest putting the jq program in a file, say my.jq, and invoking it like so:
jq -f my.jq test.json
Notice that there is no need to use "cat" in this case.
p.s. You were on the right track - try replacing |= with +=