24

I'm using SQL Server 2016, which supports JSON PATH to return JSON string. I wonder how to get just a simple empty json array, I mean [] when my query or sub-query returns null. I've tried this query:

SELECT '' AS TEST
FOR JSON PATH,ROOT('arr')

which returns:

{"arr":[{"test":""}]}

and also this one:

SELECT NULL AS TEST
FOR JSON PATH,ROOT('arr')

which returns:

{"arr":[{}]}

it's better but still not correct, I need this:

{"arr":[]}

7 Answers 7

19

You can always check this with ISNULL, e.g.:

select ISNULL( (SELECT * FROM sys.tables where 1=2 FOR JSON PATH), '[]')

If you need this in app layer, maybe it would be better to check is there some results set in data access code, and if not just return [] or {}.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the ISNULL solution suggestion. So simple and it just works!
12

This works, and can be composed within another for json query:

select json_query('[]') arr 
    for json path, without_array_wrapper

Comments

5

When nesting such subqueries, I've found that combining what others have said works best, i.e.:

  • Using COALESCE((SELECT .. FOR JSON), '[]') to prevent the null value from the subquery
  • Using JSON_QUERY() to prevent the escaping / quoting.

For example:

select
  json_query(coalesce((select 1 as b where 1 = 0 for json path), '[]')) as a
for json path;

Produces:

|JSON      |
|----------|
|[{"a":[]}]|

Without JSON_QUERY

Now the nested json array gets quoted:

select
  coalesce((select 1 as b where 1 = 0 for json path), '[]') as a
for json path;

Results in

|JSON        |
|------------|
|[{"a":"[]"}]|

Without COALESCE

Now the nested JSON is null:

select
  json_query((select 1 as b where 1 = 0 for json path)) as a
for json path`;

Results in

|JSON|
|----|
|[{}]|

1 Comment

When handling Deeply nested subqueries (eg.: relational => documentDB) This is the only answer that hits 100% accuracy every time.
1

A little manual, but if you need a quick hack, here you go:

DECLARE @JSON NVARCHAR(MAX) = (SELECT NULL AS test
FOR JSON PATH,ROOT('arr'))


SELECT REPLACE(@json, '{}', '')

Comments

1

By itself, JSON_QUERY('[]') AS [features] did not work for me. I found that the results were formatted as follows:

"features":"[]"

which was not desirable.

To get the desired result, I needed to store the JSON in a variable, then perform a REPLACE on the result, as follows:

DECLARE @json VARCHAR(MAX) = (SELECT JSON_QUERY('[]') AS [features],
                                     -- Other selected fields elided for brevity 
                                FROM MyTable
                                 FOR JSON, WITHOUT_ARRAY_WRAPPER, INCLUDE_NULL_VALUES);

SET @json = REPLACE(@json, '"features":"[]"', '"features":[]');

SELECT @json;

Yes, it's a terrible hack. But it works, and returns the result I want. Our client absolutely must have an empty array returned, and this was the best way I could find to ensure that it was present.

Comments

1

Right now I had exactly the same problem, I think this is the right way to handle it according to the microsoft documentation:

DECLARE @Array TABLE(TEST VARCHAR(100));

SELECT
    arr = ISNULL((SELECT TEST FROM @Array FOR JSON PATH), '[]')
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER

Result:

{"arr":[]}

Comments

0

Using JSON_OBJECT and JSON_ARRAY functions(SQL Server 2022):

SELECT JSON_OBJECT('arr':JSON_ARRAY())

Comments

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.