| title | Format Query Results as JSON with FOR JSON | |||
|---|---|---|---|---|
| description | Format query results as JSON, or export data from SQL Server as JSON, by adding the FOR JSON clause to a SELECT statement. | |||
| author | WilliamDAssafMSFT | |||
| ms.author | wiassaf | |||
| ms.reviewer | jovanpop, umajay, randolphwest | |||
| ms.date | 01/28/2026 | |||
| ms.service | sql | |||
| ms.topic | how-to | |||
| ms.custom |
|
|||
| helpviewer_keywords |
|
|||
| monikerRange | =azuresqldb-current || >=sql-server-2016 || >=sql-server-linux-2017 || =azuresqldb-mi-current || =fabric || =fabric-sqldb |
[!INCLUDE sqlserver2016-asdb-asdbmi-asa-serverless-pool-only-fabricse-fabricdw-fabricsqldb]
Format query results as JSON, or export data from SQL Server as JSON, by adding the FOR JSON clause to a SELECT statement. Use the FOR JSON clause to simplify client applications by delegating the formatting of JSON output from the app to [!INCLUDE ssNoVersion].
Note
The MSSQL extension for Visual Studio Code can auto-format the JSON results (as seen in this article) instead of displaying an unformatted string.
In Fabric Data Warehouse, FOR JSON must be the last operator in the query, and so you can't use it inside subqueries.
When you use the FOR JSON clause, you can specify the structure of the JSON output explicitly, or let the structure of the SELECT statement determine the output.
-
To maintain full control over the format of the JSON output, use
FOR JSON PATH. You can create wrapper objects and nest complex properties. -
To format the JSON output automatically based on the structure of the
SELECTstatement, useFOR JSON AUTO.
Here's an example of a SELECT statement with the FOR JSON clause and its output.
:::image type="content" source="media/format-query-results-as-json-with-for-json-sql-server/for-json.png" alt-text="Diagram showing how FOR JSON works.":::
In PATH mode, use the dot syntax (for example, Item.Price) to format nested output.
Here's a sample query that uses PATH mode with the FOR JSON clause. The following example also uses the ROOT option to specify a named root element.
:::image type="content" source="media/format-query-results-as-json-with-for-json-sql-server/for-json-path.png" alt-text="Diagram of flow of FOR JSON output.":::
For more detailed info and examples, see Format nested JSON output with PATH mode.
For syntax and usage, see SELECT - FOR Clause.
In AUTO mode, the structure of the SELECT statement determines the format of the JSON output.
By default, the output doesn't include NULL values. Use INCLUDE_NULL_VALUES to change this behavior.
Here's a sample query that uses AUTO mode with the FOR JSON clause.
SELECT name,
surname
FROM emp
FOR JSON AUTO;And here's the returned JSON.
[{
"name": "John"
}, {
"name": "Jane",
"surname": "Doe"
}]The following example of SELECT...FOR JSON AUTO shows what the JSON results look like when there's a 1:many relationship between data from joined tables.
This example also shows that the null value doesn't appear in the returned JSON. However, you can override this default behavior by using the INCLUDE_NULL_VALUES keyword in the FOR clause.
DROP TABLE IF EXISTS #tabStudent;
DROP TABLE IF EXISTS #tabClass;
GO
CREATE TABLE #tabClass (
ClassGuid UNIQUEIDENTIFIER NOT NULL DEFAULT newid(),
ClassName NVARCHAR(32) NOT NULL
);
CREATE TABLE #tabStudent (
StudentGuid UNIQUEIDENTIFIER NOT NULL DEFAULT newid(),
StudentName NVARCHAR(32) NOT NULL,
ClassGuid UNIQUEIDENTIFIER NULL -- Foreign key.
);
GO
INSERT INTO #tabClass (ClassGuid, ClassName)
VALUES
('DE807673-ECFC-4850-930D-A86F921DE438', 'Algebra Math'),
('C55C6819-E744-4797-AC56-FF8A729A7F5C', 'Calculus Math'),
('98509D36-A2C8-4A65-A310-E744F5621C83', 'Art Painting');
INSERT INTO #tabStudent (StudentName, ClassGuid)
VALUES
('Alice Apple', 'DE807673-ECFC-4850-930D-A86F921DE438'),
('Alice Apple', 'C55C6819-E744-4797-AC56-FF8A729A7F5C'),
('Betty Boot', 'C55C6819-E744-4797-AC56-FF8A729A7F5C'),
('Betty Boot', '98509D36-A2C8-4A65-A310-E744F5621C83'),
('Carla Cap', null);
GO
SELECT c.ClassName,
s.StudentName
FROM #tabClass AS c
RIGHT JOIN #tabStudent AS s ON s.ClassGuid = c.ClassGuid
ORDER BY c.ClassName,
s.StudentName
FOR JSON AUTO
-- To include NULL values in the output, uncomment the following line:
--, INCLUDE_NULL_VALUES
;
GO
DROP TABLE IF EXISTS #tabStudent;
DROP TABLE IF EXISTS #tabClass;
GONext is the JSON that the preceding SELECT outputs.
JSON_F52E2B61-18A1-11d1-B105-00805F49916B
[
{"s":[{"StudentName":"Carla Cap"}]},
{"ClassName":"Algebra Math","s":[{"StudentName":"Alice Apple"}]},
{"ClassName":"Art Painting","s":[{"StudentName":"Betty Boot"}]},
{"ClassName":"Calculus Math","s":[{"StudentName":"Alice Apple"},{"StudentName":"Betty Boot"}]}
]For more detailed info and examples, see Format JSON output automatically with AUTO mode.
For syntax and usage, see SELECT - FOR Clause.
Control the output of the FOR JSON clause using the following extra options.
-
ROOTTo add a single, top-level element to the JSON output, specify the
ROOToption. If you don't specify this option, the JSON output doesn't have a root element. For more info, see Add a Root Node to JSON Output with the ROOT Option. -
INCLUDE_NULL_VALUESTo include null values in the JSON output, specify the
INCLUDE_NULL_VALUESoption. If you don't specify this option, the output doesn't include JSON properties forNULLvalues in the query results. For more info, see Include Null Values in JSON - INCLUDE_NULL_VALUES Option. -
WITHOUT_ARRAY_WRAPPERTo remove the square brackets that surround the JSON output of the
FOR JSONclause by default, specify theWITHOUT_ARRAY_WRAPPERoption. Use this option to generate a single JSON object as output from a single-row result. If you don't specify this option, the JSON output is formatted as an array - that is, the output is enclosed within square brackets. For more info, see Remove Square Brackets from JSON - WITHOUT_ARRAY_WRAPPER Option.
The output of the FOR JSON clause has the following characteristics:
-
The result set contains a single column.
- A small result set can contain a single row.
- A large result set splits the long JSON string across multiple rows.
-
By default, SQL Server Management Studio (SSMS) concatenates the results into a single row when the output setting is Results to Grid. The SSMS status bar displays the actual row count.
-
Other client applications might require code to recombine lengthy results into a single, valid JSON string by concatenating the contents of multiple rows. For an example of this code in a C# application, see Use FOR JSON output in a C# client app.
:::image type="content" source="media/format-query-results-as-json-with-for-json-sql-server/for-json-output.png" alt-text="Screenshot of FOR JSON output in SQL Server Management Studio.":::
-
-
The results are formatted as an array of JSON objects.
-
The number of elements in the JSON array matches the number of rows in the results of the SELECT statement (before the FOR JSON clause is applied).
-
Each row in the results of the SELECT statement (before the FOR JSON clause is applied) becomes a separate JSON object in the array.
-
Each column in the results of the SELECT statement (before the FOR JSON clause is applied) becomes a property of the JSON object.
-
-
Both the names of columns and their values are escaped according to JSON syntax. For more info, see How FOR JSON escapes special characters and control characters.
Here's an example that demonstrates how the FOR JSON clause formats the JSON output.
| A | B | C | D |
|---|---|---|---|
| 10 | 11 | 12 | X |
| 20 | 21 | 22 | Y |
| 30 | 31 | 32 | Z |
[{
"A": 10,
"B": 11,
"C": 12,
"D": "X"
}, {
"A": 20,
"B": 21,
"C": 22,
"D": "Y"
}, {
"A": 30,
"B": 31,
"C": 32,
"D": "Z"
}]