Reputation: 79
The data that I'm trying to parse sometimes contains a single string value, other times, it contains an array of values.
For example, this works fine:
SELECT
color
FROM
OPENJSON('{"name": "Christmas Tree","color": "Green"}')
WITH (color NVARCHAR(MAX) '$.color' )
But if I have an array in there instead, it fails:
SELECT
color
FROM
OPENJSON('{"name": "Candy Cane","color": ["Red","White"]}')
WITH (color NVARCHAR(MAX) '$.color')
I can fix that by adding "AS JSON" inside the OPENJSON call:
SELECT
color
FROM
OPENJSON('{"name": "Candy Cane","color": ["Red","White"]}')
WITH (color NVARCHAR(MAX) '$.color' AS JSON)
But now the original call breaks:
SELECT
color
FROM
OPENJSON('{"name": "Christmas Tree","color": "Green"}')
WITH (color NVARCHAR(MAX) '$.color' AS JSON)
Is there a way to handle both cases in one shot? Or do I have to try one, check for a null result, then try the other?
Changing the data to be consistent isn't an option, I'm dealing with someone else's data.
I'm eventually turning the single string value into an array that contains a single value, so it's ok to return the data that way (ie, it's ok to get ['Green'] instead of 'Green')
DB-Fiddle here: https://www.db-fiddle.com/f/929e5vraAp9vsJGFPXRf5F/1
Upvotes: 3
Views: 688
Reputation: 3537
You can decode one json field in several forms in one pass:
DECLARE @data varchar(max)
SET @data = '[{"name": "Christmas Tree","color": "Green"}, {"name": "Christmas Tree","color": ["Green", "Yellow"]}]'
SELECT
ISNULL(color_array, color_scalar) as colour
FROM
OPENJSON(@data)
WITH (
color_array nvarchar(max) '$.color' as JSON,
color_scalar nvarchar(max) '$.color')
Is it what you want?
Upvotes: 2
Reputation: 1193
A little bit dodgy, however it works:
DECLARE @json NVARCHAR(MAX) = N'{"name": "Christmas Tree","color": "Green"}';
;WITH Data AS (
SELECT CASE WHEN ISJSON(j.value) > 0 THEN j.[value] ELSE '["'+j.value+'"]' END AS [value]
FROM OPENJSON(@json) j
WHERE j.[key] = 'color'
)
SELECT d.[value] AS [color]
FROM Data j
CROSS APPLY OPENJSON(j.[value]) d
;
Upvotes: 1
Reputation: 19204
This will do what you want. Again it's probably too complicated for real world situations but it may give you some insight
DECLARE @JSON VARCHAR(100)
DECLARE @V VARCHAR(50)
SET @JSON = '{"name": "Candy Cane","color": ["Red","White"]}'
SELECT @V = colour
FROM (
SELECT
color as colour
FROM
OPENJSON(@JSON)
WITH (color NVARCHAR(MAX) '$.color')
UNION ALL
SELECT
color as colour
FROM
OPENJSON(@JSON)
WITH (color NVARCHAR(MAX) '$.color' AS JSON)
) ST
WHERE colour IS NOT NULL
ORDER BY colour
SELECT @V
It's important to note the ORDER BY
. If this dataset ever returns two valid rows, you will at least consistently get the same answer.
Also I couldn't help renaming to colour ;)
Upvotes: 1