How to use jq to produce multiple JSON objects? - json

How would one transform a JSON object into several derived JSON objects with jq?
Example input:
[
{
"id": 1,
"a": "value-in-a",
"b": "value-in-b"
},
{
"id": 2,
"c": "value-in-c"
}
]
Expected output:
[
{
"id": "1",
"value": "value-in-a"
},
{
"id": "1",
"value": "value-in-b"
},
{
"id": "2",
"value": "value-in-c"
}
]
Here the output is an array with 3 elements. First 2 elements are transformed using the first element in the input array. Third element is produced from second element in the input array.
I assume to achieve there will need to be several steps:
a) Construct 2 objects from single JSON object input. Aassume this can be done using variables. First assign input object into variable, then construct object with value a and then with value b. Not sure how to make JQ return several constructed JSON objects.
b) Conditionals will need to be used to not produce an object if a, or b, or c is missing. This can probably be done using 'alternative' operator or if-then-else

You can iterate over the other keys using del and keys_unsorted:
jq 'map({id, value: (del(.id) | .[keys_unsorted[]])})'
[
{
"id": 1,
"value": "value-in-a"
},
{
"id": 1,
"value": "value-in-b"
},
{
"id": 2,
"value": "value-in-c"
}
]
Demo

Related

could not fetch json object using jsonpath

I've a requirement to fetch value from json using jayway jsonpath.
Json structure looks like below
[
{
"type": "a",
"values": [
{
"name": "a",
"value": [1,2,3]
},
{
"name": "b",
"value": [3,4,5]
},
{
"name": "c",
"value": [6,7,8]
}
]
}
]
my requirement is in the values array if the name value is a and value array contains value 1, then I need to fetch value array where name is b.
I have written jsonPath expression like below
$..values[?(#.name == 'a')]
where it is returning only
{
"name": "a",
"value": [1,2,3]
}
could someone help me in writing jsonpath expression please , Thanks in advance.
expected output
[3,4,5]
tried with
$..[?(#.values[?(#.name== 'a' && #.value CONTAINS 1)])]
then it is matching every object present in root array.
With Jayway JSONPATH you might get lucky with below jsonpath
$..[?(#.values[?(#.name=='a')].value[*] contains 1 )].values[?(#.name=='b')].value[*]

Retrieve specific value from a JSON blob in MS SQL Server, using a property value?

In my DB I have a column storing JSON. The JSON looks like this:
{
"views": [
{
"id": "1",
"sections": [
{
"id": "1",
"isToggleActive": false,
"components": [
{
"id": "1",
"values": [
"02/24/2021"
]
},
{
"id": "2",
"values": []
},
{
"id": "3",
"values": [
"5393",
"02/26/2021 - Weekly"
]
},
{
"id": "5",
"values": [
""
]
}
]
}
]
}
]
}
I want to create a migration script that will extract a value from this JSON and store them in its own column.
In the JSON above, in that components array, I want to extract the second value from the component with an ID of "3" (among other things, but this is a good example). So, I want to extract the value "02/26/2021 - Weekly" to store in its own column.
I was looking at the JSON_VALUE docs, but I only see examples for specifing indexes for the json properties. I can't figure out what kind of json path I'd need. Is this even possible to do with JSON_VALUE?
EDIT: To clarify, the views and sections components can have static array indexes, so I can use views[0].sections[0] for them. Currently, this is all I have with my SQL query:
SELECT
*
FROM OPENJSON(#jsonInfo, '$.views[0].sections[0]')
You need to use OPENJSON to break out the inner array, then filter it with a WHERE and finally select the correct value with JSON_VALUE
SELECT
JSON_VALUE(components.value, '$.values[1]')
FROM OPENJSON (#jsonInfo, '$.views[0].sections[0].components') components
WHERE JSON_VALUE(components.value, '$.id') = '3'

Create merged JSON array from multiple files using jq

I have multiple JSON files one.json, two.json, three.json with the below format and I want to create a consolidated array from them using jq. So, from all the files I want to extract Name and Value field inside the Parameters and use them to create an array where the id value will be constructed from the Name value and value field will be constructed using Value field value.
input:
one.json:
{
"Parameters": [
{
"Name": "id1",
"Value": "one",
"Version": 2,
"LastModifiedDate": 1581663187.36
}
]
}
two.json
{
"Parameters": [
{
"Name": "id2",
"Value": "xyz",
"Version": 2,
"LastModifiedDate": 1581663187.36
}
]
}
three.json
{
"Parameters": [
{
"Name": "id3",
"Value": "xyz",
"Version": 2,
"LastModifiedDate": 1581663187.36
}
]
}
output:
[
{
"id": "id1",
"value": "one"
},
{
"id": "id2",
"value": "xyz"
},
{
"id": "id3",
"value": "xyz"
}
]
How to achieve this using jq
You can use a reduce expression instead of slurping the whole file into memory (-s); by iterative manipulation of the input file contents and then appending the required fields one at a time.
jq -n 'reduce inputs.Parameters[] as $d (.; . + [ { id: $d.Name, value: $d.Value } ])' one.json two.json three.json
The -n flag is to ensure that we construct the output JSON data from scratch over the input file contents made available over the inputs function. Since reduce works in an iterative manner, for each of the object in the input, we create a final array, creating the KV pair as desired.

Jq convert an object into an array

I have the following file "Pokemon.json", it's a stripped down list of Pokémon, listing their Pokédex ID, name and an array of Object Types.
[{
"name": "onix",
"id": 95,
"types": [{
"slot": 2,
"type": {
"name": "ground"
}
},
{
"slot": 1,
"type": {
"name": "rock"
}
}
]
}, {
"name": "drowzee",
"id": 96,
"types": [{
"slot": 1,
"type": {
"name": "psychic"
}
}]
}]
The output I'm trying to achieve is, extracting the name value of the type object and inserting it into an array.
I can easily get an array of all the types with
jq -r '.pokemon[].types[].type.name' pokemon.json
But I'm missing the key part to transform the name field into it's own array
[ {
"name": "onix",
"id": 95,
"types": [ "rock", "ground" ]
}, {
"name": "drowzee",
"id": 96,
"types": [ "psychic" ]
} ]
Any help appreciated, thank you!
In the man it states you have an option to use map - which essentially means walking over each result and returning something (in our case, same data, constructed differently.)
This means that for each row you are creating new object, and put some values inside
Pay attention, you do need another iterator within, since we want one object per row.
(we simply need to map the values in different way it is constructed right now.)
So the solution might look like so:
jq -r '.pokemon[]|{name:.name, id:.id, types:.types|map(.type.name)}' pokemon.json

Filter JSON list based on an element appearing in a member's list using jq

I'm using jq to try to filter a JSON list based on the content of a list inside the objects within that list. Here's a sample of my JSON document:
{
"modules": [
{
"path": [
"root"
],
"outputs": {
"a": "b",
"c": "d"
}
},
{
"path": [
"other1"
],
"outputs": {
"e": "f",
"g": "h"
}
},
{
"path": [
"other2"
],
"outputs": {
"i": "j",
"k": "l"
}
}
]
}
I want to filter the modules list to the object where the path list contains "root", then return the outputs object. Essentially I want to return:
{"a":"b","c":"d"}
which I can do using jq .modules[0].outputs (see example on http://jqplay.org) but I don't want to make an assumption that the object I'm interested in is the 0th element of the modules list, instead I want to filter the modules list where the path list contains an element "root".
How can I do that?
Typical, as soon as I post the question I stumble upon the answer through trial and error.
.modules[] | select(.path == ["root"]).outputs
see example on jqplay.org