TSQL JSON How to add an array to an existing Json Object? - json

We've got a SQL query where we create a JSON file with for JSON Path.
We want to merge 2 JSON objects into 1 JSON. But we struggle with the code how to accomplish this task.
We tried JSON_MODIFY to merge them together using append. But this did not work for us.
What we'd like to do is this, we have 2 seperate json objects and we want to merge them as one.
Json Object A:
{
"ID" : 0,
"Name" : "a name",
"Description" : "a description"
}
and Json Object B
"Nodes" : [
{
"NodeID" : 10,
"NodeName" : "Node 0"
},
{
"NodeID" : 11,
"NodeName" : "Node 1"
}
]
What we want to have:
{
"ID" : 0,
"Name" : "a name",
"Description" : "a description",
"Nodes" : [
{
"NodeID" : 10,
"NodeName" : "Node 0"
},
{
"NodeID" : 11,
"NodeName" : "Node 1"
}
]
}
Our current SQL Query looks like this:
set #JsonCourse = ( select c.name, c.id, c.description from dbo.courses c where c.id = #id for json path)
set #JsonNodes = ( select n.id, n.name from dbo.nodes n where n.courseId = #id for json path, root('Nodes'))
set #CompleteJson = JSON_MODIFY(#JsonCourse,'append $',JSON_QUERY(#JsonNodes));
print #CompleteJson
But our result is like this:
[
{
"ID" : 0,
"Name" : "a name",
"Description" : "a description"
},
{
"Nodes" : [
{
"NodeID" : 10,
"NodeName" : "Node 0"
},
{
"NodeID" : 11,
"NodeName" : "Node 1"
}
]
}
]
Note: we've used hypothetical data here.
How do we fix this with JSON_MODIFY?

So I'll add another answer, as this is a completely different thing as the first answer:
As I do not have your tables, I'll set the JSON variables to the values you provided
DECLARE #json1 NVARCHAR(MAX)=
N'{
"ID" : 0,
"Name" : "a name",
"Description" : "a description"
}'
DECLARE #json2 NVARCHAR(MAX)= --<-- had to add the surrounding {}, otherwise this was invalid JSON
N'{"Nodes" :
[
{
"NodeID" : 10,
"NodeName" : "Node 0"
},
{
"NodeID" : 11,
"NodeName" : "Node 1"
}
]}';
--We do not need append here.
--We have to tell the engine the name of the new node.
--To avoid repeated key Nodes I read from the #json2 using $.Nodes as path
DECLARE #CompleteJSON NVARCHAR(MAX)=JSON_MODIFY(#Json1,'$.Nodes',JSON_QUERY(#Json2,'$.Nodes'));
PRINT #CompleteJSON;
I hope this is closer to your needs...

Please read about creating a MCVE. This is a stand-alone sample, which makes your issue reproducible, and helps us to provide easy answers...
If I got this correctly there is a 1:n related structure, where each node in your "object A" can have several nodes in "object B".
My following code will simulate this through INFORMATION_SCHEMA. Each table as 1 or many columns.
We solve this with a correlated sub-query. This is the way to create nested JSON arrays:
SELECT TOP 3 t.TABLE_NAME AS NodeName
,t.TABLE_TYPE AS NodeType
,(
SELECT TOP 3 c.COLUMN_NAME AS ColumnName
,c.DATA_TYPE AS ColumnType
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_CATALOG=t.TABLE_CATALOG
AND c.TABLE_SCHEMA=t.TABLE_SCHEMA
AND c.TABLE_NAME=t.TABLE_NAME
FOR JSON PATH
) AS MyColumns
FROM INFORMATION_SCHEMA.TABLES t
FOR JSON PATH;
The result
[
{
"NodeName": "spt_fallback_db",
"NodeType": "BASE TABLE",
"MyColumns": [
{
"ColumnName": "xserver_name",
"ColumnType": "varchar"
},
{
"ColumnName": "xdttm_ins",
"ColumnType": "datetime"
},
{
"ColumnName": "xdttm_last_ins_upd",
"ColumnType": "datetime"
}
]
},
{
"NodeName": "spt_fallback_dev",
"NodeType": "BASE TABLE",
"MyColumns": [
{
"ColumnName": "xserver_name",
"ColumnType": "varchar"
},
{
"ColumnName": "xdttm_ins",
"ColumnType": "datetime"
},
{
"ColumnName": "xdttm_last_ins_upd",
"ColumnType": "datetime"
}
]
},
{
"NodeName": "spt_fallback_usg",
"NodeType": "BASE TABLE",
"MyColumns": [
{
"ColumnName": "xserver_name",
"ColumnType": "varchar"
},
{
"ColumnName": "xdttm_ins",
"ColumnType": "datetime"
},
{
"ColumnName": "xdttm_last_ins_upd",
"ColumnType": "datetime"
}
]
}
]
As you can see, each table as a nested set of columns, represented through a JSON array.

Related

jslt access parent field in for expression

Hi, I want to use jslt to transform json , but happen an unsolvable problem.
The input json data like this
{
"user_id": "001",
"friends": [{
"friend_id": "002"
}, {
"friend_id": "003"
}, {
"friend_id": "004"
}]
}
Then , what output json data I expected like the follow :
[{
"user_id": "001",
"friend_id": "002"
}, {
"user_id": "001",
"friend_id": "003"
}, {
"user_id": "001",
"friend_id": "004"
}]
In jslt expression , I use expression of for to traverse the array field friends :
[
for (.friends) {
"user_id": .user_id,
"friend_id": .friend_id
}
]
However , the treansform result can't get field user_id
[{
"friend_id": "002"
}, {
"friend_id": "003"
}, {
"friend_id": "004"
}]
How can I access field user_id out of the scope related array field friends ?
Looking forward for your help, thanks !
The other answer is correct, but more complex than it needs to be. This is enough:
let user_id = (.user_id)
[ for (.friends) { "user_id": $user_id , "friend_id" : .friend_id } ]
Note that if you really want to report errors you could do it like this:
if (.user_id and .friends)
let user_id = (.user_id)
[ for (.friends) { "user_id": $user_id , "friend_id" : .friend_id } ]
else if (not(.user_id))
error("user_id field missing")
else
error("friends field missing")
Using error turns this into an exception at the Java level.
The reason the parent operator is not supported is that Jackson doesn't have a parent pointer in its nodes. That's a performance feature, because it means the node can be reused several places, saving CPU and memory.
You'll need to use a variable for the user_id, which you can then reference in the loop.
The following should fit your requirement:
if (.user_id)
let user = .user_id
if (.friends)
[
for (.friends) {
"user_id": $user,
"friend_id": .friend_id
}
]
else
error("missing key 'friends'")
else
error("missing key 'user_id'")

converted json result structure not same as source

i have test case to compare against the source kept in Kafka message.
I noticed the structured is not same.
no missing field, but the structure is not arranged in the same sequence.
how do i make the result converted same as the source structure?
code to retrieve the message, then decode the base64 format and prettyprint the result.
def responseList = new JsonSlurper().parseText(consumeMessage.getResponseText())
println('response text: \n' + JsonOutput.prettyPrint(JsonOutput.toJson(responseList)))
def decoded = new JsonSlurper().parseText(new String(responseList[0].value.decodeBase64()))
println('response decoded text: \n' + JsonOutput.prettyPrint(JsonOutput.toJson(decoded)))
below is the result printed at console
2019-11-20 16:36:44.934 DEBUG oingDRToAllocationVerification-DynamicID - 10: decoded = JsonSlurper().parseText(new java.lang.String(responseList[0].value.decodeBase64()))
2019-11-20 16:36:44.945 DEBUG oingDRToAllocationVerification-DynamicID - 11: println("response decoded text:
" + JsonOutput.prettyPrint(JsonOutput.toJson(decoded)))
response decoded text:
{
"contexts": [
{
"activityId": "c2884e63-d30d-48a3-965c-0b33202885c2",
"incomingTimestamp": "2019-11-20T08:36:29.0829958Z",
"sourceName": "DispenseOrderService",
"timestamp": "2019-11-20T08:36:29.0829958+00:00",
"userId": "unknown"
}
],
"dispenseOrder": [
{
"dispenseRequestType": "DISPENSEORDER",
"id": "6320112019043628",
"items": [
{
"administrationInstructions": "drug intake information test 123",
"dispenseAsWritten": false,
"id": "cda92ec7-3191-4b7b-a972-7f4545146db4",
"itemId": "Augmentn",
"quantity": 100
},
{
"administrationInstructions": "drug intake information test 234",
"dispenseAsWritten": false,
"id": "19e00776-b08d-47c8-930b-76ddc01f0ff4",
"itemId": "Clopidogrl",
"quantity": 200
},
{
"administrationInstructions": "drug intake information test 456",
"dispenseAsWritten": true,
"id": "0a5b0f4a-366d-4fa7-a0b8-2e8c83f4af13",
"itemId": "Adenosine",
"quantity": 300
}
],
"locationId": "Pharmacy Jewel East",
"piiIdentifiers": {
"doctorId": "b502f046-fb1e-4fcf-8135-a7a13cfb47f6",
"patientId": "fe49b461-8eeb-46d5-b995-a31cdaaa35f3",
"pharmacistId": "b502f046-fb1e-4fcf-8135-a7a13cfb47f6"
},
"priority": 4,
"state": "NEW",
"type": "Test ingest type"
}
],
"messageClass": "DispenseRequestV1",
"messageId": "83e94dac-dfb6-49d7-8ca0-219d155fecce",
"notifications": [
],
"operation": "Add",
"timestamp": "2019-11-20T08:36:29.0952632+00:00"
}
below is the source. the result after conversion is not same as source. as in the structure is not arranged accordingly.
{
"operation" : "Add",
"dispenseOrder" : [ {
"id" : "6320112019043628",
"locationId" : "Pharmacy Jewel East",
"piiIdentifiers" : {
"patientId" : "fe49b461-8eeb-46d5-b995-a31cdaaa35f3",
"doctorId" : "b502f046-fb1e-4fcf-8135-a7a13cfb47f6",
"pharmacistId" : "b502f046-fb1e-4fcf-8135-a7a13cfb47f6"
},
"priority" : 4,
"state" : "NEW",
"type" : "Test ingest type",
"dispenseRequestType" : "DISPENSEORDER",
"items" : [ {
"id" : "cda92ec7-3191-4b7b-a972-7f4545146db4",
"itemId" : "Augmentn",
"quantity" : 100,
"dispenseAsWritten" : false,
"administrationInstructions" : "drug intake information test 123"
}, {
"id" : "19e00776-b08d-47c8-930b-76ddc01f0ff4",
"itemId" : "Clopidogrl",
"quantity" : 200,
"dispenseAsWritten" : false,
"administrationInstructions" : "drug intake information test 234"
}, {
"id" : "0a5b0f4a-366d-4fa7-a0b8-2e8c83f4af13",
"itemId" : "Adenosine",
"quantity" : 300,
"dispenseAsWritten" : true,
"administrationInstructions" : "drug intake information test 456"
} ]
} ],
"messageId" : "83e94dac-dfb6-49d7-8ca0-219d155fecce",
"timestamp" : "2019-11-20T08:36:29.0952632+00:00",
"messageClass" : "DispenseRequestV1",
"contexts" : [ {
"userId" : "unknown",
"timestamp" : "2019-11-20T08:36:29.0829958+00:00",
"activityId" : "c2884e63-d30d-48a3-965c-0b33202885c2",
"incomingTimestamp" : "2019-11-20T08:36:29.0829958Z",
"sourceName" : "DispenseOrderService"
} ],
"notifications" : [ ]
}
As json.org says:
An object is an unordered set of name/value pairs.
So, different JSON methods/libraries might order them in a different way. You shouldn't rely on order of name/value pairs when working with JSON.
(If order is very important to you, you might try using suggested solution from this post.)

How to extract key-value pair from nested json

I have as nested json object like this
{
"id": 1,
"parentId": null,
"name": "Product",
"children": [
{
"id": 50,
"parentId": 1,
"name": "Bicycle",
"children": [
{
"id": 100,
"parentId": 50,
"name": "Tire"
}
]
}
]
}
Oddly I have figured out how to build the nested tree from the result but not how to reverse it.
I have tried using lodash _.flatten and _.flattendeep but having one of those days where I can't get my head around this. Also the object can be of unknown depth. Any thoughts ?
My desired result is this.
[
{"id" : 1, "parentId" : null, "Product" },
{"id" : 50, "parentId" : 1 , "Bicycle"},
{"id" : 100, "parentId" : 50 , "Tire"}
]
not a very optimal solution but just an idea, NOTE: if dataset is very large there might be some performance issues.
resultsArray = [];
function flatten(obj) {
const { id, parentId, name, children} = obj;
if(children && children.length) {
children.map(child => flatten(child));
}
resultsArray.push({id, parentId, name});
}

How to print this specific JSON in a Mat Table?

I have this specific JSON file I'm not allowed to change, which looks like this :
{
"computers" : {
"John" : {
"version" : "1.42.0",
"environment" : "Default",
"platform" : "x64",
"admin" : "true"
},
"Peter" : {
"version" : "1.43.6",
"environment" : "Default",
"platform" : "x64",
"admin" : "true"
},
"Eric" : {
"version" : "1.43.6",
"environment" : "Default",
"platform" : "x64",
"admin" : "false"
}
}
I use the JSON.parse() method to parse the file and I put it into a MatTableDataSource.
Problem is, when I need to display it in my MatTable, I can't really access it the way I want.
I have a column where I want to display all version parameters, so for this I can't say : this.dataSource.computers.????.version
Do you guys see where I'm getting at ? Do you have any idea of what I can do differently in order to solve this ?
Looking forward to reading you.
The Angular mat-table requires the input data to be in an array. First, we use Object.keys() to extract the keys, which will contain the list of names. Then, we can use Object.values() to other values within each key in array format. This is followed by mapping the above array objects with the name property from the list of names.
const data = {
"computers": {
"John": {
"version": "1.42.0",
"environment": "Default",
"platform": "x64",
"admin": "true"
},
"Peter": {
"version": "1.43.6",
"environment": "Default",
"platform": "x64",
"admin": "true"
},
"Eric": {
"version": "1.43.6",
"environment": "Default",
"platform": "x64",
"admin": "false"
}
}
};
const nameList = Object.keys(data.computers);
const dataList = Object.values(data.computers).map((obj, index) => {
obj['name'] = nameList[index];
return obj;
});
console.log(dataList);

How to fetch the data in the mongodb

How to fetch the data from the json file using mongoshell
I want to fecch the Data by policyID
Say in the json file I sent the PolicyID is 3148
I tried could of ways to write the command but say 0 rows fetched.
db.GeneralLiability.find({"properties.id":"21281"})
db.GeneralLiability.find({properties:{_id:"21281"}})
Do i need to set any thing else?index,cursors etc?
Sample json
{
"session": {
"data": {
"account": {
"properties": {
"userName": "abc.com",
"_dateModified": "2014-10-01",
"_manuscript": "Carrier_New_Rules_2_1_0",
"_engineVersion": "2.0.0",
"_cultureCode": "en-US",
"_cultureName": "United States [english]",
"_context": "Underwriter",
"_caption": "Carrier New Rules (2.1.0)",
"_id": "p1CEB08012E51477C9CD0E89FE77F5E51"
},
"properties": {
"_xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"_xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"_id": "3148",
"_HistoryID": "5922",
"_Type": "onset",
"_Datestamp": "2014-10-01T04:46:33",
"_TransactionType": "New",
"_EffectiveDate": "2014-01-01",
"_Charge": "1599",
"_TransactionGroup": "t4CE4FA751F9C400D9007E692A883DA66",
"_PolicyID": "3148",
"_Index": "1",
"_Count": "1",
"_Sequence": "1"
}
}
}
This will return the document with _PolicyID = "3148":
db.GeneralLiability.find({
"session._PolicyID": "3148"
}).pretty();
You have some issues in your document formatting. First off I am pretty sure that using underscores are reserved for mongo (I could be wrong). Either way it is bad form. I have restructured your data for you. I am not sure why you wanted to nest your data so much, but I am guessing you had a good reason for it.
You will notice that I am using the ObjectID from Mongo for my _id:
{
"_id" : ObjectId("56e1c1f53bac31a328e3682b"),
"session" : {
"data" : {
"account" : {
"properties" : {
"xmlns:xsd" : "http://www.w3.org/2001/XMLSchema",
"xmlns:xsi" : "http://www.w3.org/2001/XMLSchema-instance",
"HistoryID" : "5922",
"Type" : "onset",
"Datestamp" : "2014-10-01T04:46:33",
"TransactionType" : "New",
"EffectiveDate" : "2014-01-01",
"Charge" : "1599",
"TransactionGroup" : "t4CE4FA751F9C400D9007E692A883DA66",
"PolicyID" : "3148",
"Index" : "1",
"Count" : "1",
"Sequence" : "1"
}
}
}
}
}
Now if you run this command it will return your document:
{ "session.data.account.properties.PolicyID": "3148" }