Append in nested array JSON object in oracle - json

I have JSON document column in one of the table and its structure is like:-
{
"root":[{"MCR":"MCR_1",
"MCR_COLUMNS":{
"MCR_COLUMN_1":"ABC1",
"MCR_COLUMN_2":"ABC2"
}
},
{"MCR":"MCR_2",
"MCR_COLUMNS":{
"MCR_COLUMN_1":"XYZ1",
"MCR_COLUMN_2":"XYZ2"
}
}
]
}
Now I want to write a merge statement to merge in this document to manage two cases
CASE-1) If MCR value is already present in document, then directly append MCR_COLUMN_x and its value to JSON object of its MCR_COLUMNS. eg. I want to append
{"MCR":"MCR_1",
"MCR_COLUMNS":{
"MCR_COLUMN_3":"ABC3"
}
}
so, the updated document should be
{
"root":[{"MCR":"MCR_1",
"MCR_COLUMNS":{
"MCR_COLUMN_1":"ABC1",
"MCR_COLUMN_2":"ABC2",
"MCR_COLUMN_3":"ABC3"
}
},
{"MCR":"MCR_2",
"MCR_COLUMNS":{
"MCR_COLUMN_1":"XYZ1",
"MCR_COLUMN_2":"XYZ2"
}
}
]
}
CASE-2) If MCR value does not exist then it appends a new JSON object into the root array. for eg: if i want to append
{"MCR":"MCR_3",
"MCR_COLUMNS":{
"MCR_COLUMN_1":"UVW1",
"MCR_COLUMN_2":"UVW2"
}
}
then updated document should be
{
"root":[{"MCR":"MCR_1",
"MCR_COLUMNS":{
"MCR_COLUMN_1":"ABC1",
"MCR_COLUMN_2":"ABC2"
}
},
{"MCR":"MCR_2",
"MCR_COLUMNS":{
"MCR_COLUMN_1":"XYZ1",
"MCR_COLUMN_2":"XYZ2"
}
},
{"MCR":"MCR_3",
"MCR_COLUMNS":{
"MCR_COLUMN_1":"UVW1",
"MCR_COLUMN_2":"UVW2"
}
}
]
}
I had tried JSON_mergepatch and JSON_Transform but case-1 I'm not able to achieve. And since I'll not have before-hand knowledge whether MCR is already present or not, I just can not only right solution for case-2.
Any help or suggestion will be very much appreciated.

To check if the MCR value exists:
WHERE json_exists(json_value, '$?(#.root[*].MCR == "MCR_1")')
To add an item to MCR_COLUMNS
update test_js
set json_value = json_transform(
json_value,
INSERT '$.root.MCR_COLUMNS.MCR_COLUMN_3' = 'ABC3'
)
where json_exists(json_value, '$?(#.root[*].MCR == "MCR_1")')
;
To add an item to root array:
update test_js
set json_value = json_transform(
json_value,
APPEND '$.root' = '{"MCR":"MCR_3", "MCR_COLUMNS":{ "MCR_COLUMN_1":"UVW1", "MCR_COLUMN_2":"UVW2" } }' FORMAT JSON
)
where not json_exists(json_value, '$?(#.root[*].MCR == "MCR_3")')
;

In addition to #p3consulting's answer, to insert into a particular array element only(here in this case 'MCR_1') further conditions can be applied to INSERT.
update test_js
set json_value = json_transform( json_value, INSERT '$.root[*]?(#.MCR=="MCR_1").MCR_COLUMNS.MCR_COLUMN_4' = 'ABC4') )
where json_exists(json_value, '$?(#.root[*].MCR == "MCR_1")') ;

Related

Get array from json in Bigquery

I'm trying to get the data from a JSON in BigQuery. This JSON is Stored in a one-column table.
So far, I've been able to get only the "variables" array, with the following:
Select JSON_QUERY_ARRAY(Column1, '$.sessions[0].variables') FROM Table
How can I get the other values/arrays (sessionMessage and events)? I can't make it work..
I've tried with:
JSON_VALUE(Column1, '$.sessions[0].conversation')
JSON_QUERY_ARRAY(Column1, '$.sessions[0].sessionMessages')
But I get only empty values (The original json has values inside this arrays..)
{
"fromDate":"2020-04-10T23:47:17.161Z",
"pageRows":151,
"sessions":[
{
"variables":[],
"sessionDate":"2020-04-10T23:47:17.161Z",
"botMessages":2,
"userHasTalked":"true",
"topics":[
"TOPIC1"
],
"sessionId":"WXXXSXSXSXXXQ_2020-01-00T23:47:17.161Z",
"platformContactId":"XXXXXXX-XXXXXXX-XXXXXXXXXXXXXX",
"sessionMessages":[.....],
"queues":[
"QUEUE1",
"QUEUE2"
],
"customerId":"SSDSDS",
"userMessages":2,
"operatorMessages":1,
"sessionMessagesQty":2,
"sessionStartingCause":"Organic",
"channelId":"IDCHANEL",
"conversation":"https://url.com",
"events":[.....]
}
],
"toDate":"2020-04-10T23:47:17.161Z",
"hasMore":true,
"pageToken":"XXXXXXXXXXXXXX"
}
There is nothing wrong with the function and JSONPath that you used, but your sample JSON file has some unexpected thing, like [.....], removing/replacing those and query below works fine:
WITH a as (select
"""
{
"fromDate":"2020-04-10T23:47:17.161Z",
"pageRows":151,
"sessions":[
{
"variables":[],
"sessionDate":"2020-04-10T23:47:17.161Z",
"botMessages":2,
"userHasTalked":"true",
"topics":[
"TOPIC1"
],
"sessionId":"WXXXSXSXSXXXQ_2020-01-00T23:47:17.161Z",
"platformContactId":"XXXXXXX-XXXXXXX-XXXXXXXXXXXXXX",
"sessionMessages":[1,2,3],
"queues":[
"QUEUE1",
"QUEUE2"
],
"customerId":"SSDSDS",
"userMessages":2,
"operatorMessages":1,
"sessionMessagesQty":2,
"sessionStartingCause":"Organic",
"channelId":"IDCHANEL",
"conversation":"https://url.com",
"events":[],
}
],
"toDate":"2020-04-10T23:47:17.161Z",
"hasMore":true,
"pageToken":"XXXXXXXXXXXXXX"
}
""" data)
SELECT JSON_VALUE(data, '$.sessions[0].conversation'),
JSON_QUERY_ARRAY(data, '$.sessions[0].sessionMessages')
FROM a;

How to retrieve values from an array of json objects in PostgreSQL?

I have the following json :
[
{
"transition":"random_word",
"from":"paris",
"to":"porto",
"date":{
"date":"2020-05-28 11:51:25.201864",
"timezone_type":3,
"timezone":"Europe\/Paris"
}
},
{
"transition":"rainbow",
"from":"porto",
"to":"faro",
"date":{
"date":"2020-06-06 23:10:06.878539",
"timezone_type":3,
"timezone":"Europe\/Paris"
}
},
{
"transition":"banana",
"from":"faro",
"to":"rio_de_janeiro",
"date":{
"date":"2020-06-06 23:14:10.975099",
"timezone_type":3,
"timezone":"Europe\/Paris"
}
},
{
"transition":"hello",
"from":"rio_de_janeiro",
"to":"buenos_aires",
"date":{
"date":"2020-06-06 23:14:15.314370",
"timezone_type":3,
"timezone":"Europe\/Paris"
}
}
]
Imagine I want to retrieve the last stop of my traveler (the value of the key "to" from the last json object. Here : buenos_aires) and the date (here :2020-06-06 23:14:15.314370).
How should I proceed knowing that I want to do that using PostgreSQL?
If with "last" you mean the order in which the elements show up in the array, you can use jsonb_array_length() to get the length of the array and use that to obtain the last element:
select (the_json_column -> jsonb_array_length(the_json_column) - 1) ->> 'to' as "to",
(the_json_column -> jsonb_array_length(the_json_column) - 1) #>> '{date,date}' as "date"
from the_table
The expression jsonb_array_length(the_json_column) - 1 calculates the index of the "last" element in the array.
If your column is defined as json rather than jsonb (which it should be) you need to use the equivalent json_array_length() instead.

Get Json key using JsonPath

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

Parsing json : Test is json key existing

I'm request with API REST a JIRA filter since Excel and I return my result in a json object.
I'm parsing this object and I Try to show my result (in a msgbox for now) but I have a problem when the json Key doesn't exist !
A extract of my json :
{
"expand":"schema,names",
"startAt":0,
"maxResults":500,
"total":2,
"issues":[
{
"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields",
"id":"00001",
"fields":{
"components":[
{
"id":"01",
"name":"component_1"
},
{
"id":"02",
"name":"component_02"
}
]
}
},
{
"expand":"operations,versionedRepresentations,editmeta,changelog,renderedFields",
"id":"00002",
"fields":{
"components":[
]
}
},
]
}
As you cans see, in my first issue (id 00001) I have a 2 components key but in my second issus (id 0002) I don't have component key, because this fields is empty in JIRA for this issue.
So, a part of my code to show my result :
For Each Item In jsonObject("issues")
issueId = Item("id")
compoId1 = Item("fields")("components")(1)("id")
compoId2 = Item("fields")("components")(2)("id")
i = i + 1
'PRINT_OF_MY_RESULT
Next
My problem :
If my issue (00001) has a "component" value, it's OK and I can return my result but ... if my issus (00002) hasn't a result, my code failled to define compoId ... and my code crash.
Did you have a simple solution ? I try somethings with Exists, isEmpty, etc etc ... but nothing concluent for me :(
You can modify your solution some what like this,
For Each Item In jsonObject("issues")
issueId = Item("id")
For Each componentItem In jsonObject(Item("fields")("components"))
If componentItem("id")==1 then
compoId1 = componentItem("id")
EndIf
If componentItem("id")==1 then
compoId2 = componentItem("id")
EndIf
Next
i = i + 1
'PRINT_OF_MY_RESULT
Next

How to access the value in key value pair when the key is a changing value?

I have this JSON data stored in variable result, now I want to access the value of result.metadata.data.s1[1].lily , however the key Lily is not known and it may change on server side, so I stored the key as a variable, like var key1 = "Lily". How to access the value with this var key1 ?
{
"metadata":{
"data":{
"s1":[
{
"Lily":"chat",
"time":10
},
{
"Mancy":"chat1",
"time":10
},
{
"John":"chat2",
"time":10
}
],
"s2":[
{
"Lan":"chat3",
"time":10
},
{
"Yoyo":"chat6",
"time":10
}
]
}
}
}
If you always know it's the first item in the list, bracket notation should work fine.
result.metadata.data.s1[0][key1];
If you're not sure where it falls, then the [0] won't always be correct, and you'll have to iterate through all of the items in the result.metadata.data.s1 array to find it.
Your code above is getting the second item in the list, at index [1], and the key there is not "Lily", it's "Mancy".
Here's a codepen demo