Create nested JSON arrays using FOR JSON PATH
You can use the following query:
SELECT pr.person_id AS [person.id], pr.person_name AS [person.name],
(
SELECT pt.pet_id AS id, pt.pet_name AS name
FROM @Pets pt WHERE pt.pet_owner=pr.person_id
FOR JSON PATH
) AS [person.pet]
FROM @Persons pr
FOR JSON PATH, ROOT('pet owners')
For more information, see https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/10/09/returning-child-rows-formatted-as-json-in-sql-server-queries/
SQL - How to store JSON_QUERY output to variable
Following VBokšić's link I made this query as answer:
DECLARE @json NVARCHAR(MAX)
SET @json = (SELECT (JSON_QUERY((
SELECT 'Ball' AS title,
'Blue' AS color, (
SELECT '1' AS Opt1,
'2' AS Opt2
FOR JSON PATH
) AS Options
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
))) AS product
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
SELECT @json
Output:
{"product":{"title":"Ball","color":"Blue","Options":[{"Opt1":"1","Opt2":"2"}]}}
Return results in custom JSON format
You may try with the following statement, using FOR JSON PATH
and dot-separated column names:
Statement:
SELECT
'12345' AS 'values.param1',
'abcdef' AS 'values.param2'
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
Result:
{"values":{"param1":"12345","param2":"abcdef"}}
How do I deserialize a JSON array without needing a wrapper type?
Just deserialize the vector directly:
let workspaces = serde_json::from_str::<Vec<Workspace>>(input);
How do you OPENJSON on Arrays of Arrays
While you can't get away with using only a single OPENJSON, you can simplify your query a bit to make it easier to create dynamically by removing the nested subqueries:
SELECT SectionName, SectionOrder, RenderName, RenderOrder, FieldName, FieldData
FROM OPENJSON(@layout, '$.Sections')
WITH (
SectionName NVARCHAR(MAX) '$.SectionName',
SectionOrder NVARCHAR(MAX) '$.SectionOrder',
Renders NVARCHAR(MAX) '$.Renders' AS JSON
)
CROSS APPLY OPENJSON(Renders,'$')
WITH (
RenderName NVARCHAR(MAX) '$.RenderName',
RenderOrder NVARCHAR(MAX) '$.RenderOrder',
Fields NVARCHAR(MAX) '$.Fields' AS JSON
)
CROSS APPLY OPENJSON(Fields,'$')
WITH (
FieldName NVARCHAR(MAX) '$.FieldName',
FieldData NVARCHAR(MAX) '$.FieldData'
)
EDIT:
If you have a primitive array, you can access the data using the value
property after you expose the nested array as a JSON field. Using the JSON from the comment below, you can do this to get the values from a primitive array:
DECLARE @layout NVARCHAR(MAX) = N'{ "id":123, "locales":["en", "no", "se"] }'
SELECT
a.id
, [Locale] = b.value
FROM OPENJSON(@layout, '$')
WITH (
id INT '$.id',
locales NVARCHAR(MAX) '$.locales' AS JSON
) a
CROSS APPLY OPENJSON(a.locales,'$') b
Select last value from Json array
You can try this
DECLARE @json NVARCHAR(MAX) =
N'{
"solution": "xxxxxxxxxxxxxxxxxxxxx",
"options": [
{
"choice_id": 205073,
"choice": "aaaa"
},
{
"choice_id": 205074,
"choice": "bbbb"
},
{
"choice_id": 205075,
"choice": "cccc"
},
{
"choice_id": 205076,
"choice": "dddd"
}
]
}';
SELECT TOP 1
A.solution
,JSON_QUERY(B.[value]) AS options
FROM OPENJSON(@json) WITH (solution nvarchar(max), options NVARCHAR(MAX) AS JSON) A
CROSS APPLY OPENJSON(A.options) B
ORDER BY B.[key] DESC
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;
The result
{"solution":"xxxxxxxxxxxxxxxxxxxxx"
,"options":{
"choice_id": 205076,
"choice": "dddd"
}
}
Some explanation
FROM OPENJSON
will dive into your JSON and find the top-level elements. We fetch solution
as is and we state AS JSON
for options
to specify, that this value will be treated as JSON later on.
The CROSS APPLY
will call OPENJSON
again, but this time against the options
and we will get an array back. The column key
is the ordinal position within the array, so we can use TOP 1
and ORDER BY key DESC
to get the last element in the array.
Before we can re-assemble this query to a JSON we have to wrap B.value
with JSON_QUERY()
. Otherwise we would see escaped characters like \t
or \r\n
within the JSON. The reason: Without this, the JSON-string would not be taken as a JSON-string but as any other string and would be packed into the result as one single text value.
Related Topics
Postgres Drop Table Syntax Error
How to Insert to a Column Whose Name Is a SQL Keyword
SQL Server 2005: How to Subtract 6 Month
Bulk Load Data Conversion Error (Truncation)
How to Use in Clause with Preparedstatement in Postgresql
SQL Developer "Disconnected from the Rest of the Join Graph"
Postgres SQL 'Could Not Determine Data Type of Parameter' by Hibernate
Oracle SQL - Add Primary Key to Table
Max Row Size in SQL Server 2012 with Varchar(Max) Fields
SQL Azure: What Will Happen If Size of My SQL Azure Get 5Gb
Always Show Decimal Places in SQL
Ssrs Grey Out Parameter Based on Result from Other Parameter
Reference Value of Serial Column in Another Column During Same Insert
How to Use the Results of a Stored Procedure from Within Another