I have JSON like this:
{
"_key": {
"id": "3b8d1ed7-c3ec-32ec-a083-2ddc17152e94",
"rootId": "15c85327-9628-3685-b84a-375b546ba92a",
},
"employeeInfo": {
"idNumber": "3",
"gender": "Male",
"age": 20,
....
},
"product": {
"plan": "prod",
"class": "1",
"_type": "Product",
...
}
}
And I want to receive new JSON with desired fields. I’m using next query:
SELECT
'{ "employeeInfo": {"age: ' +
JSON_VALUE(info, '$.employeeInfo.age') + ', "gender": ' +
JSON_VALUE(info, '$.employeeInfo.gender') + ' }' AS info
FROM
item.[Item] AS c
INNER JOIN
(SELECT "rootId", MAX("revisionNo") AS maxRevisionNo
FROM item."Item"
WHERE "rootId" = 'E3B455EF-D48E-338C-B6D4-FFD8B41243F9'
GROUP BY "rootId") AS subquery ON c."rootId" = subquery."rootId";
And I get this response:
{ "employeeInfo": {"age: 38, "gender": Female }
But it seems JSON_VALUE
doesn’t return type, so Female is without quotes. I don’t know what fields will be requested, so I can’t add quotes myself. How can I execute a query to return values with their types. I.e. I expect next response:
{ "employeeInfo": {"age: 38, "gender": "Female" }
I’m using this SQL Server version:
Microsoft Azure SQL Edge Developer (RTM) - 15.0.2000.1552 (ARM64)
UPD: I’m already have solution for postgres:
SELECT jsonb_strip_nulls(json_build_object('employee_info', json_build_object('age', c."info"->'employeeInfo' -> 'age', 'gender', c."info"->'employeeInfo' -> 'gender'), 'product', c."info"->'product')::jsonb) as info ...
And also need to build a request for sql-server. I will build this request dynamically when receive field names.
2
Answers
You may try to build the expected JSON with
FOR JSON PATH
and dot-separated column names for nested content, not with string concatenation. The documentation explains howFOR JSON
converts SQL Server data types to JSON data types:Note, that with the additional
INCLUDE_NULL_VALUES
modifier, you may include the possibleNULL
values in the generated JSON.JSON_VALUE()
always returnsnvarchar(4000)
andFOR JSON
converts the values as JSON strings. If you need the actual data types, a solution is an explicit convertion withCONVERT()
or anOPENJSON()
call with explicit schema with actual columns data types.SQL Server and Azure have limited JSON capabilities. If you do not know the actual data types of the referenced JSON properties, you need to call
OPENJSON()
with default schema and analyze the result (a table with columnskey
,value
andtype
). A possible approach, parsing only the$.employeeInfo
part of the stored JSON, is the following statement:A slightly better syntax for @zhorov’s excellent answer.
ROOT
parameter instead of adding it to the column name.$.employeeInfo
directly intoOPENJSON
If you want to do it completely dynamically then you need
OPENJSON
without a schema. Then rebuild it using a combination ofSTRING_AGG
CONCAT
andSTRING_ESCAPE
.