1

I have a SQL Server Table with a JSON column. In it, I have a property 'Code' that contained a string with one value. Now, I want that 'Code' to be an Array to be able to contain more than one strings.

How can I update all my table values to change the property to an array?

"Code" : null --> "Code" : []
"Code" : "XX" --> "Code" : ["XX"]
3
  • Assuming every object currently contains only scalar values for Code, UPDATE MyTable SET jsonColumn = JSON_MODIFY(jsonColumn, '$.Code', CONCAT('[', JSON_VALUE(jsonColumn, '$.Code'), ']')). If we cannot assume this things get much trickier. Commented Mar 10, 2022 at 15:29
  • @JeroenMostert, that would work with int, but no with strings, as it loses the " "Code" : "XX" would be changed to "Code" : [XX] and I want it to be "Code" : ["XX"] Commented Mar 10, 2022 at 15:35
  • Oh, right. Yeah, that's quite a bit more complicated, since we have to get JSON_QUERY and/or OPENJSON involved. Oh well, that's why it's not an answer. :P Commented Mar 10, 2022 at 15:36

1 Answer 1

3

You may try to modify the stored JSON as text using OPENJSON() with default schema to get the type of the $.Code part:

Sample data:

SELECT *
INTO Data
FROM (VALUES
   (CONVERT(nvarchar(max), N'{"Code": "XX"}')),
   (CONVERT(nvarchar(max), N'{"Code": null}')),
   (CONVERT(nvarchar(max), N'{"Code": 1}')),
   (CONVERT(nvarchar(max), N'{"Code": []}')),
   (CONVERT(nvarchar(max), N'{"Code": {}}'))
) d (JsonColumn)

Statement:

UPDATE d
SET JsonColumn = JSON_MODIFY(
   JsonColumn, 
   '$.Code', 
   JSON_QUERY(CONCAT('[', j.[value], ']'))
)
FROM Data d
OUTER APPLY (
   SELECT 
      CASE 
         WHEN [type] = 0 THEN ''
         WHEN [type] = 1 THEN CONCAT('"', STRING_ESCAPE([value], 'json'), '"')
         WHEN [type] = 2 THEN [value]
         ELSE '"not a scalar value"'
      END AS [value]
   FROM OPENJSON(d.JsonColumn, '$')
   WHERE [key] = 'Code'
) j

Result:

JsonColumn
--------------------------------
{"Code": ["XX"]}
{"Code": []}
{"Code": [1]}
{"Code": ["not a scalar value"]}
{"Code": ["not a scalar value"]}

You may consider the @JeroenMostert's comment and use something like this:

UPDATE d
SET JsonColumn = JSON_MODIFY(
   JsonColumn, 
   '$.Code', 
   JSON_QUERY(CONCAT('[', j.[value], ']'))
)
FROM Data d
OUTER APPLY (
   SELECT IIF ([type] = 1, CONCAT('"', STRING_ESCAPE([value], 'json'), '"'), [value]) AS [value]
   FROM OPENJSON(d.JsonColumn, '$')
   WHERE [key] = 'Code'
) j
Sign up to request clarification or add additional context in comments.

4 Comments

This can be made a bit shorter by using the CASE [type] WHEN... syntax (same semantics, of course). Also, don't forget to STRING_ESCAPE([value], 'json') in the case of strings.
@JeroenMostert, thanks, STRING_ESCAPE() is very important.
The "not a scalar value" thing seems unwise (and unnecessary); simply interpolating value again should usually work. In fact, IIF ([type] = 1, CONCAT('"', STRING_ESCAPE([value], 'json'), '"'), [value]) should cover everything, since really only strings are special.
Yeah, mine is still going on or I would have posted an answer myself. :P

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.