get Json values and Json string from Json Array in SQL Server - sql

I have a JSON string like this:
{
"success": "true",
"data": [
{ "ID": 1, "name": "abc" },
{ "ID": 2, "name": "def" }
]
}
I need output like below:
ID
name
JsonString
1
abc
{"ID": 1, "name": "abc"}
2
def
{"ID": 2, "name": "def"}
I need the query in SQL Server

The only interesting things here are the initial path to OPENJSON (since we only care about data) and the property JsonString reflecting the original JSON, which needs a path and an override.
DECLARE #json NVARCHAR(MAX) = '{"success":"true","data":[{"ID":1,"name":"abc"},{"ID":2,"name":"def"}]}';
SELECT *
FROM OPENJSON(#json, '$.data')
WITH (ID INT, name VARCHAR(100), JsonString NVARCHAR(MAX) '$' AS JSON)

Related

Is there an UPDATE equivalent command to SELECT json data

Is there a way to update the data retrieved from the below select (in this case, change "MS220" to something else)? It's difficult enough to do select from JSON in some cases. I'm not sure how to update just a single element.
CREATE TABLE JData (
JsonData nvarchar(max)
)
INSERT INTO JData
(JsonData)
VALUES
('[
{
"Categories": [
{
"QuerySourceNames": [
"QAsset"
],
"Id": "eceae85a-ffc6-49f4-8f6a-78ce2b4b274e",
"Name": "emsdba"
}
],
"Id": "525b4f07-0f67-43ac-8070-a0e6c1ceb1b9",
"Name": "MS220"
}
]')
SELECT
ParamName
FROM [dbo].[JData] jsonData
CROSS APPLY OPENJSON (jsonData)
WITH
(
Categories nvarchar(max) AS json,
Id uniqueidentifier,
ParamName varchar(10) '$.Name'
);
Try JSON_MODIFY() with the path '$[0].Name'
UPDATE d
SET jsonData = JSON_MODIFY(jsonData, '$[0].Name', 'New Value')
FROM [dbo].[JData] d
Results:
[
{
"Categories": [
{
"QuerySourceNames": [
"QAsset"
],
"Id": "eceae85a-ffc6-49f4-8f6a-78ce2b4b274e",
"Name": "emsdba"
}
],
"Id": "525b4f07-0f67-43ac-8070-a0e6c1ceb1b9",
"Name": "New Value"
}
]
db<>fiddle here

Transform properties from JSON array into comma-separated string

I have a string column in an SQL-Server table on Azure which contains the following data:
{
"status": "success",
"data": [
{
"name": "Jane",
"type": 0
},
{
"name": "John",
"type": 0
}
]
}
How can it be transformed into a comma-separated string containing "Jane, John"?
Here how to achieve this via a snippet of some of my older code, you should be able to loop through the table and do this for each row. There may be a quicker way of doing it but this will work.
DECLARE #JSON NVARCHAR(200) = '{"status": "success", "data": [{"name": "Jane", "type": 0},{"name": "John", "type": 0}]}',
#result nvarchar(max) = ''
SELECT #result = #result + [value] + N', '
FROM (
SELECT DISTINCT data.value
FROM OPENJSON(#JSON, '$.data') as jsondata
CROSS APPLY OPENJSON(jsondata.value) as data
WHERE data.[key] = 'name') a
select #result = substring(#result, 1, (LEN(#result)-1))
select #result

Update JSON array using SQL Server

I have JSON like below:
{
"property": {
"commonProperty": "abc",
"Items": [
{
"ID": 1,
"Name": "a"
},
{
"ID": 2,
"Name": "a"
},
{
"ID": 3,
"Name": "b"
}
]
}
}
And what I want to achieve is to update Names to "c" where it's currently "a" using SQL Server (so I want to have result like below).
{
"property": {
"commonProperty": "abc",
"Items": [
{
"ID": 1,
"Name": "c"
},
{
"ID": 2,
"Name": "c"
},
{
"ID": 3,
"Name": "b"
}
]
}
}
As far as I know I cannot use JSON_MODIFY because it does not handles queries inside it's arguments and OPENJSON cannot be updated. Is there any method I can use?
EDIT note: added common property above Items.
You may try one of the following options:
Parse the '$.property.Items' JSON array as table using OPENJSON(), make an update, output the table's content as JSON using FOR JSON and modify the original JSON using JSON_MODIFY():
Build a dynamic statement. You can modify the input JSON using JSON_MODIFY() and the appropriate path. The path needs to be defined as a literal or from SQL Server 2017 as a variable, but using a wildcard is not possible (e.g. the statement SELECT #json = JSON_MODIFY(#json, '$.property.Items[0].Name', N'c') modifies the first item in the Items JSON array).
JSON:
DECLARE #json nvarchar(max) = N'{
"property":{
"commonProperty":"abc",
"Items":[
{
"ID":1,
"Name":"a"
},
{
"ID":2,
"Name":"a"
},
{
"ID":3,
"Name":"b"
}
]
}
}'
Statement (that parses the JSON as a table, modifies the table and outputs the table's content as JSON):
SELECT #json = JSON_MODIFY(
#json,
'$.property.Items',
(
SELECT
ID AS 'ID',
CASE WHEN Name = N'a' THEN N'c' ELSE Name END AS 'Name'
FROM OPENJSON(#json, '$.property.Items') WITH (ID int, Name nvarchar(50))
FOR JSON PATH
)
)
Dynamic statement:
DECLARE #stm nvarchar(max)
SET #stm = (
SELECT N'SET #json = JSON_MODIFY(#json, ''$.property.Items[' + [key] + N'].Name'', N''c''); '
FROM OPENJSON(#json, '$.property.Items')
WHERE JSON_VALUE([value], '$.Name') = N'a'
FOR XML PATH('')
)
PRINT #stm
EXEC sp_executesql #stm, N'#json nvarchar(max) OUTPUT', #json OUTPUT

Parse JSON text inside NVARCHAR column when using FOR JSON PATH

Suppose that I have a table with a records like this:
CREATE TABLE json_store (
[id] INT IDENTITY(1, 1) PRIMARY KEY,
[json_data] NVARCHAR(MAX)
)
id | json_data
------------------------------------------
1 | {"data_in_json": "Hello from 1"}
2 | {"data_in_json": "Hello from 2"}
3 | {"data_in_json": "Hello from 3", "remarks": "I have a different structure"}
and I want a JSON result like this:
[
{
"id": 1,
"json_data": {"data_in_json": "Hello from 1"}
},
{
"id": 2,
"json_data": {"data_in_json": "Hello from 2"}
},
{
"id": 3,
"json_data": {"data_in_json": "Hello from 3", "remarks": "I have a different structure"}
}
]
I've been using FOR JSON PATH but the problem is it returns JSON as an escaped string.
SELECT [id], [json_data]
FROM [json_store]
FOR JSON PATH
[
{
"id": 1,
"json_data": "{\"data_in_json\": \"Hello from 1\"}"
},
{
"id": 2,
"json_data": "{\"data_in_json\": \"Hello from 2\"}"
},
{
"id": 3,
"json_data": "{\"data_in_json\": \"Hello from 3\", \"remarks\": \"I have a different structure\"}"
}
]
I wanted to know is it possible to parse a JSON column along with the result?
Also, I've tried using OPENJSON() to parse and use FOR JSON PATH convert it back to JSON but it does break the structure into [{"key": ..., "value": ...}, ...]
You need to convert your NVARCHAR(MAX) column json_data to JSON first, using JSON_QUERY, so that SQL Server knows it is already JSON and won't escape it:
CREATE TABLE #T (id INT, json_data NVARCHAR(MAX));
INSERT #T(id, json_data)
VALUES
(1, '{"data_in_json": "Hello from 1"}'),
(2, '{"data_in_json": "Hello from 2"}'),
(3, '{"data_in_json": "Hello from 3", "remarks": "I have a different structure"}');
SELECT id, JSON_QUERY(t.json_data) AS json_data
FROM #T AS t
FOR JSON AUTO;
Which gives:
[
{
"id": 1,
"json_data": {
"data_in_json": "Hello from 1"
}
},
{
"id": 2,
"json_data": {
"data_in_json": "Hello from 2"
}
},
{
"id": 3,
"json_data": {
"data_in_json": "Hello from 3",
"remarks": "I have a different structure"
}
}
]

SQL Query to get the count of Json Array

I have the below Json object. How do I get the count of Object Array.
{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC"
},
{
"ID": 11,
"Name": "ABCD"
},
]
}]}
I tried the below query but seems JSON_Length was not available.
SELECT ModelName,
JSON_LENGTH(JsonData, '$.Model[0].Object')
FROM TabA
The expected output should be
ModelName COUNT
Test Model 2
If you have valid JSON (at the moment you have a trailing comma (,_ after one of your closing braces (})), then you could use OPENJSON and COUNT:
DECLARE #JSON nvarchar(MAX) = N'{
"Model": [
{
"ModelName": "Test Model",
"Object": [
{
"ID": 1,
"Name": "ABC"
},
{
"ID": 11,
"Name": "ABCD"
}
]
}]}';
SELECT M.ModelName,
COUNT(O.[key]) AS [Count]
FROM (VALUES(#JSON))V(J)
CROSS APPLY OPENJSON(V.J)
WITH(ModelName varchar(20) '$.Model[0].ModelName',
[Object] nvarchar(MAX) '$.Model[0].Object' AS JSON) M
CROSS APPLY OPENJSON(M.[Object]) O
GROUP BY M.ModelName;