19

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 ?

izengod
  • 1,116
  • 5
  • 17
  • 41
  • 2
    SQL Server 2016 CTP3.2 added `without_array_wrapper`... Sample: `select top 5 (select a.* for json path, without_array_wrapper) from sys.objects a` – Jason Goemaat Sep 07 '18 at 22:54

3 Answers3

43

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)
)
Jeroen Mostert
  • 27,176
  • 2
  • 52
  • 85
  • @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.) – Jeroen Mostert Jun 16 '17 at 07:31
  • Still useful in 2022. – abhi Sep 01 '22 at 17:30
  • 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. – CodePT Mar 28 '23 at 11:00
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)
Nenad Zivkovic
  • 18,221
  • 6
  • 42
  • 55
Barak Yellin
  • 81
  • 1
  • 1
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?).