Get Json key using JsonPath - json

I am struggling to write a JsonPath query to extract particular keys from the following sample Json.
{
"initial": "somevalue",
"somekey2": {
"inner1": "innerval1",
"inner2": "innerval2"
}
}
For example:
1) I wish to extract the first key, which in this case is initial. Is this possible using JsonPath?
2) Get an inner key such as inner1. Something similar to $."initial"."somekey2" but returning an array with just the keys (inner1 and inner2).

This SO question covers it.
$.*~ returns
[
"initial",
"somekey2"
]
$.somekey2.*~ returns
[
"inner1",
"inner2"
]
To get all 2nd order children use $.*.*~. Basically for nth order, $.(n times *).*~

not sure about json path, but suppose your object is a
a={
"initial": "somevalue",
"somekey2": {
"inner1": "innerval1",
"inner2": "innerval2"
}
};
the you can get all keys by using Object.keys(a)
that will give array of keys ["initial", "somekey2"]
then you can use that key to revtrive its nested value
a[Object.keys(a)[1]] // returns {inner1: "innerval1", inner2: "innerval2"}
and you can repeat the same for all nested element

Related

jq join on common key

I'm very new to jq and this post is a result of not understanding the mechanics behind jq.
I could develop a bash script, which does what I want but jq and it's JSON super-powers have intrigued me and I'd like to learn it by applying to real world scenarios. Here's one...
BTW, I've tried to make use of the existing jq related SO solutions for merging/joining JSONs but have failed.
The closest I came to what I needed was to use an INDEX and a concatenation of $x + . , however I was only getting the LAST item from my second (c2) json.
So, my problem is as follows:
There are Two JSON files:
JSON #1 will have unique "id" and "type" keys - among other key/value pairs, which I've removed for better clarity of my post.
JSON #2 will contain multiples/non-unique "type" keys, which I'd like to match these two JSON files on. This JSON #2 will also contain other key/value pairs, which are expected to be contained in the resultant output.
My output requirements are:
I'd like to obtain a (one per line or a single array) list of all combinations of matching key/values pairs between c1 and c2 array where the value of the "type" key (string) matches between c1 and c2 exactly.
One more question, how much more difficult would it be to scale the solution to perform similar matching/joining between three JSON files at once - again on the same value of a particular key?
Any assistance or even just hints on how to solve and understand how to solve this would be greatly appreciated!
1st input file: JSON #1, Array c1 (collection 1)
{ "c1":
[
{ "c1id":1, "type":"alpha" },
{ "c1id":2, "type":"beta" }
]
}
2nd input file: JSON #2, Array c2 (collection 2)
{
"c2":
[
{ "c2id":1,"type":"alpha","serial":"DDBB001"} ,
{ "c2id":2,"type":"beta","serial":"DDBB007"} ,
{ "c2id":3,"type":"alpha","serial":"DDTT005"} ,
{ "c2id":4,"type":"beta","serial":"DDAA002"} ,
{ "c2id":5,"type":"yotta","serial":"DDCC017"}
]
}
Expected output:
{"c1id":1,"type":"alpha","c2id":1,"serial":"DDBB001"}
{"c1id":1,"type":"alpha","c2id":3,"serial":"DDTT005"}
{"c1id":2,"type":"beta","c2id":2,"serial":"DDBB007"}
{"c1id":2,"type":"beta","c2id":4,"serial":"DDAA002"}
You will notice that type "yotta" from the c2 is not included in the output. This is expected. Only "types" which exist in c1 and match c2 are expected to be in the results. I guess this is implied by this being a matching/joining exercise - I added it just for clarity - I hope it worked.
Here's an example of using INDEX and JOIN:
jq --compact-output --slurpfile c1 c1.json '
INDEX(
$c1[0].c1[];
.type
) as $index |
JOIN(
$index;
.c2[];
.type;
reverse|add
)
' c2.json
The first argument to INDEX needs to produce a stream of items, which is why we apply [] to get the items from the array individually. The second argument selects our index key.
We use the four argument version of JOIN. The first argument is the index itself, the second is a stream of objects to be joined to the index, the third argument selects the lookup key from the streamed objects, and the fourth argument is an expression to assemble the join object. The input to that expression is a stream of two-item arrays, each looking something like this:
[{"c2id":1,"type":"alpha","serial":"DDBB001"},{"c1id":1,"type":"alpha"}]
Since we just want to combine all the keys and values from the objects we just use add, but we first reverse the array to nicely arrange the c1 fields before the c2 fields. The end result is as you hoped:
{"c1id":1,"type":"alpha","c2id":1,"serial":"DDBB001"}
{"c1id":2,"type":"beta","c2id":2,"serial":"DDBB007"}
{"c1id":1,"type":"alpha","c2id":3,"serial":"DDTT005"}
{"c1id":2,"type":"beta","c2id":4,"serial":"DDAA002"}

JSONPath issu returning value using a filter

I have the following json, for which I'm having trouble selecting one of the values using a filter. Specifically, I want to return "POS_Undeclared"
{"wd:Program_of_Study_Reference": {
"wd:ID": [
{
"#wd:type": "WID",
"$": "123456789abcde"
},
{
"#wd:type": "Program_of_Study_ID",
"$": "POS_Undeclared"
}
]
}
}
This jsonpath $.wd:Program_of_Study_Reference.wd:ID[1].$ gives me what I need, but I cannot count on the ordering to be consistent or even exist, hence cannot use [1] .
I cannot seem to get a filter like #wd:type == Program_of_Study_ID to work. I'm guessing it is the # and/or the : goofing up my syntax.
How can I filter to get the value POS_Undeclared ?
Try using
$.wd:Program_of_Study_Reference.*[?(#['#wd:type'] == "Program_of_Study_ID")].$

Is it possible to get a sorted list of attribute values from a JSON array using JSONPath

Given JSON like:
[
{
"Serial no": 994,
},
{
"Serial no": 456,
}
]
I know this query will give me an array of all Serial no values, in the order they are in the JSON: $..['Serial no']
I'm not sure exactly what sorting capabilities JSONPath has but I think you can use / and \ to sort - but how are they used to modify my query string in this case? I am only interested doing this in pure JSONPath, not JS or post-query sorting - that's easy, I just want to know if I can avoid it.
This is a source I found suggesting sorting is supported but it might be product-specific?
I'm using http://www.jsonquerytool.com/ to test this

PostgreSQL: Querying a table based on the existence of a dynamic field in an object nested inside another object which is in an array of objects

In a table items, I have a jsonb column called users. The JSON structure of users follows the following example:
[
{
"required": 1,
"agents": {
"user1": "A",
"user2": "P",
"user3": "A"
}
},
{
"required": 3,
"agents": {
"user1": "P",
"user4": "P",
"user5": "P"
}
}
]
Note that the table items has many fields, but for the sake of simplicity, we can consider that it has only an item_id and a users field. And all answers I saw here on SO provide queries for elements of objects directly inside an array.
I also wish I could rewrite the object's structure in a better way, but it's not my decision in this case :D.
I'm new to JSON queries in postgres, so I tried to write a few queries without success.
Question:
I'm trying to find a query, that can return all items that have a key 'user4' inside the agents sub-object of any element in the array. Any suggestions?
Use the function jsonb_array_elements() and the ? operator:
select i.*
from items i
cross join jsonb_array_elements(users)
where value->'agents' ? 'user4'
See JSON Functions and Operators.

Diplaying JSON multidimensional array

I have this JSON array, but I don't know how display it.
{
"grupy": [{
"id_grupa_parametrow": "1",
"id_grupa_nadrzedna": "0",
"nazwa_grupy": "1_1",
"opis_grupy": "hdghgh",
"kolejnosc": "1233"
}]
}
I tried:
result["grupy"].id_grupa_parametrow;
but it doesn't work.
You can use some online json editors to find your data easily. Anyway, you have an array defined for groupy index. So, use numerical indexes first:
result["grupy"][0].id_grupa_parametrow;
What you have to know is that {} means that it's an object and [] is an array. So result in an object which has grupy property - that's why you have to use a dot here - result.grupy.
grupy is an array to you should use [0] index - result.grupy[0].
And so on...
This is the right way in this case:
result.grupy[0].id_grupa_parametrow;
result.grupy[0].id_grupa_parametrow;