Get multiple rows using FOR JSON clause
Asked Answered
M

3

20

Using PostgreSQL I can have multiple rows of json objects.

select (select ROW_TO_JSON(_) from (select c.name, c.age) as _) as jsonresult from employee as c

This gives me this result:

{"age":65,"name":"NAME"}
{"age":21,"name":"SURNAME"}

But in SqlServer when I use the FOR JSON AUTO clause it gives me an array of json objects instead of multiple rows.

select c.name, c.age from customer c FOR JSON AUTO

[{"age":65,"name":"NAME"},{"age":21,"name":"SURNAME"}]

How to get the same result format in SqlServer ?

Manton answered 24/4, 2017 at 11:51 Comment(1)
SQL Server 2016 CTP3.2 added without_array_wrapper... Sample: select top 5 (select a.* for json path, without_array_wrapper) from sys.objects aTailpipe
A
47

By constructing separate JSON in each individual row:

SELECT (SELECT [age], [name] FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)
FROM customer

There is an alternative form that doesn't require you to know the table structure (but likely has worse performance because it may generate a large intermediate JSON):

SELECT [value] FROM OPENJSON(
    (SELECT * FROM customer FOR JSON PATH)
)
Alinealinna answered 24/4, 2017 at 12:44 Comment(3)
@Mathew: yes, see updated question. I don't know of a way to do this that will have good performance; ask a separate question if that's a concern. (Or, you know, just write out the columns, SELECT * is recommended against for a reason.)Alinealinna
Still useful in 2022.Area
Worked like a charm, the only thing I was missing was the INCLUDE_NULL_VALUES option for null values that I wanted anyway, gonna leave it here, might help someone.Franks
S
8

no structure better performance

SELECT c.id, jdata.*
FROM customer c
  cross apply 
    (SELECT * FROM customer jc where jc.id = c.id FOR JSON PATH , WITHOUT_ARRAY_WRAPPER) jdata (jdata)
Svoboda answered 25/12, 2018 at 16:35 Comment(1)
Thanks a lot. The other answers doesn`t work for mePlaint
T
0

Same as Barak Yellin but more lazy:

1-Create this proc

CREATE PROC PRC_SELECT_JSON(@TBL VARCHAR(100), @COLS VARCHAR(1000)='D.*') AS BEGIN
EXEC('
SELECT X.O FROM ' + @TBL + ' D
CROSS APPLY (
    SELECT ' + @COLS + '
    FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) X (O)
')
END

2-Can use either all columns or specific columns:

CREATE TABLE #TEST ( X INT, Y VARCHAR(10), Z DATE )
INSERT #TEST VALUES (123, 'TEST1', GETDATE())
INSERT #TEST VALUES (124, 'TEST2', GETDATE())

EXEC PRC_SELECT_JSON #TEST

EXEC PRC_SELECT_JSON #TEST, 'X, Y'

If you're using PHP add SET NOCOUNT ON; in the first row (why?).

Telecommunication answered 10/11, 2021 at 23:8 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.