---
title: "JSON_QUERY (Transact-SQL)"
description: JSON_QUERY extracts an object or an array from a JSON string.
author: WilliamDAssafMSFT
ms.author: wiassaf
ms.reviewer: jovanpop, umajay, randolphwest
ms.date: 10/27/2025
ms.service: sql
ms.subservice: t-sql
ms.topic: reference
ms.custom:
- ignite-2025
f1_keywords:
- "JSON_QUERY"
- "JSON_QUERY_TSQL"
helpviewer_keywords:
- "JSON, extracting"
- "JSON, querying"
- "JSON_QUERY function"
dev_langs:
- TSQL
monikerRange: "=azuresqldb-current || =azure-sqldw-latest || >=sql-server-2016 || >=sql-server-linux-2017 || =azuresqldb-mi-current || =fabric || =fabric-sqldb"
---
# JSON_QUERY (Transact-SQL)
[!INCLUDE [sqlserver2016-asdb-asdbmi-asa-fabricse-fabricdw-fabricsqldb](../../includes/applies-to-version/sqlserver2016-asdb-asdbmi-asa-fabricse-fabricdw-fabricsqldb.md)]
The `JSON_QUERY` syntax extracts an object or an array from a JSON string.
To extract a scalar value from a JSON string instead of an object or an array, see [JSON_VALUE](json-value-transact-sql.md). For info about the differences between `JSON_VALUE` and `JSON_QUERY`, see [Compare JSON_VALUE and JSON_QUERY](../../relational-databases/json/validate-query-and-change-json-data-with-built-in-functions-sql-server.md#JSONCompare).
:::image type="icon" source="../../includes/media/topic-link-icon.svg" border="false"::: [Transact-SQL syntax conventions](../../t-sql/language-elements/transact-sql-syntax-conventions-transact-sql.md)
## Syntax
```syntaxsql
JSON_QUERY ( expression [ , path ] [ WITH ARRAY WRAPPER ] )
```
## Arguments
#### *expression*
An expression. Typically the name of a variable or a column that contains JSON text.
If `JSON_QUERY` finds JSON that isn't valid in *expression* before it finds the value identified by *path*, the function returns an error. If `JSON_QUERY` doesn't find the value identified by *path*, it scans the entire text and returns an error if it finds JSON that isn't valid anywhere in *expression*.
#### *path*
A JSON path that specifies the object or the array to extract.
In [!INCLUDE [sssql17-md](../../includes/sssql17-md.md)] and in [!INCLUDE [ssazure-sqldb](../../includes/ssazure-sqldb.md)], you can provide a variable as the value of *path*.
The JSON path can specify lax or strict mode for parsing. If you don't specify the parsing mode, lax mode is the default. For more info, see [JSON Path Expressions in the SQL Database Engine](../../relational-databases/json/json-path-expressions-sql-server.md).
The default value for *path* is `$`. As a result, if you don't provide a value for *path*, `JSON_QUERY` returns the input *expression*.
If the format of *path* isn't valid, `JSON_QUERY` returns an error.
#### *WITH ARRAY WRAPPER*
> [!NOTE]
> `WITH ARRAY WRAPPER` is currently in preview and only available in [!INCLUDE [sssql25-md](../../includes/sssql25-md.md)].
The ANSI SQL `JSON_QUERY` function is currently used to return a JSON object or array in a specified path. With the support for [array wildcards](../../relational-databases/json/json-path-expressions-sql-server.md#array-wildcard-and-range-support) in SQL/JSON path expression introduced in [!INCLUDE [sssql25-md](../../includes/sssql25-md.md)], `JSON_QUERY` can be used to return specified properties of elements in a JSON array where each element is a JSON object. Since wildcard searches can return multiple values, specify the `WITH ARRAY WRAPPER` clause in a JSON query expression along with a SQL/JSON path expression with wildcard or range or list to return the values as a JSON array. `WITH ARRAY WRAPPER` clause is supported only if the input is a **json** type.
Consider the following JSON document:
```sql
DECLARE @j AS JSON = '{
"id": 2,
"first_name": "Mamie",
"last_name": "Baudassi",
"email": "mbaudassi1@example.com",
"gender": "Female",
"ip_address": "148.199.129.123",
"credit_cards": [
{
"type": "jcb",
"card#": "3545138777072343",
"currency": "Koruna"
},
{
"type": "diners-club-carte-blanche",
"card#": "30282304348533",
"currency": "Dong"
},
{
"type": "jcb",
"card#": "3585303288595361",
"currency": "Yuan Renminbi"
},
{
"type": "maestro",
"card#": "675984450768756054",
"currency": "Rupiah"
},
{
"type": "instapayment",
"card#": "6397068371771473",
"currency": "Euro"
}
]
}';
```
The path `$.credit_cards` points to a JSON array where each element is a valid JSON object. Now, the `JSON_QUERY` function can be used with array wildcard support to return all or specific values of the `type` property like:
```sql
SELECT JSON_QUERY(@j, '$.credit_cards[*].type' WITH ARRAY WRAPPER);
```
The following table shows various examples of SQL/JSON path expression with wildcard and the return value using `JSON_QUERY WITH ARRAY WRAPPER`.
| Path | Return value |
| --- | --- |
| `$.credit_cards[0].type` | `["jcb"]` |
| `$.credit_cards[*].type` | `["jcb","diners-club-carte-blanche","jcb","maestro","instapayment"]` |
| `$.credit_cards[0, 2].type` | `["jcb","jcb"]` |
| `$.credit_cards[1 to 3].type` | `["diners-club-carte-blanche","jcb","maestro"]` |
| `$.credit_cards[last].type` | `["instapayment"]` |
| `$.credit_cards[last, 0].type` | `["instapayment","jcb"]` |
| `$.credit_cards[last, last].type` | `["instapayment","instapayment"]` |
| `$.credit_cards[ 0, 2, 4].type` | `["jcb","jcb","instapayment"]` |
## Return value
Returns a JSON fragment of type **nvarchar(max)**. The collation of the returned value is the same as the collation of the input expression.
If the value isn't an object or an array:
- In lax mode, `JSON_QUERY` returns null.
- In strict mode, `JSON_QUERY` returns an error.
## Remarks
### Lax mode and strict mode
Consider the following JSON text:
```json
{
"info": {
"type": 1,
"address": {
"town": "Cheltenham",
"county": "Gloucestershire",
"country": "England"
},
"tags": ["Sport", "Water polo"]
},
"type": "Basic"
}
```
The following table compares the behavior of `JSON_QUERY` in lax mode and in strict mode. For more info about the optional path mode specification (lax or strict), see [JSON Path Expressions in the SQL Database Engine](../../relational-databases/json/json-path-expressions-sql-server.md).
| Path | Return value in lax mode | Return value in strict mode | More info |
| --- | --- | --- | --- |
| `$` | Returns the entire JSON text. | Returns the entire JSON text. | |
| `$.info.type` | `NULL` | Error | Not an object or array.
Use `JSON_VALUE` instead. |
| `$.info.address.town` | `NULL` | Error | Not an object or array.
Use `JSON_VALUE` instead. |
| `$.info."address"` | `N'{ "town":"Cheltenham", "county":"Gloucestershire", "country":"England" }'` | `N'{ "town":"Cheltenham", "county":"Gloucestershire", "country":"England" }'` | |
| `$.info.tags` | `N'[ "Sport", "Water polo"]'` | `N'[ "Sport", "Water polo"]'` | |
| `$.info.type[0]` | `NULL` | Error | Not an array. |
| `$.info.none` | `NULL` | Error | Property doesn't exist. |
### Use JSON_QUERY with FOR JSON
`JSON_QUERY` returns a valid JSON fragment. As a result, `FOR JSON` doesn't escape special characters in the `JSON_QUERY` return value.
If you're returning results with FOR JSON, and you're including data that's already in JSON format (in a column or as the result of an expression), wrap the JSON data with `JSON_QUERY` without the *path* parameter.
## Examples
### A. Return a JSON fragment
The following example shows how to return a JSON fragment from a `CustomFields` column in query results.
```sql
SELECT PersonID,
FullName,
JSON_QUERY(CustomFields, '$.OtherLanguages') AS Languages
FROM Application.People;
```
### B. Include JSON fragments in FOR JSON output
The following example shows how to include JSON fragments in the output of the FOR JSON clause.
```sql
SELECT StockItemID,
StockItemName,
JSON_QUERY(Tags) AS Tags,
JSON_QUERY(CONCAT('["', ValidFrom, '","', ValidTo, '"]')) AS ValidityPeriod
FROM Warehouse.StockItems
FOR JSON PATH;
```
### C. Use WITH ARRAY WRAPPER with JSON_QUERY function
The following example shows the use of `WITH ARRAY WRAPPER` with the `JSON_QUERY` function to return multiple elements from a JSON array:
```sql
DECLARE @j JSON = '
{"id":2, "first_name":"Mamie", "last_name":"Baudassi", "email":"mbaudassi1@example.com", "gender":"Female", "ip_address":"148.199.129.123", "credit_cards":[ {"type":"jcb", "card#":"3545138777072343", "currency":"Koruna"}, {"type":"diners-club-carte-blanche", "card#":"30282304348533", "currency":"Dong"}, {"type":"jcb", "card#":"3585303288595361", "currency":"Yuan Renminbi"}, {"type":"maestro", "card#":"675984450768756054", "currency":"Rupiah"}, {"type":"instapayment", "card#":"6397068371771473", "currency":"Euro"}]}
';
SELECT JSON_QUERY(@j, '$.credit_cards[*].type' WITH ARRAY WRAPPER ) as credit_card_types;
```
[!INCLUDE [ssresult-md](../../includes/ssresult-md.md)]
```output
credit_card_types
--------
["jcb","diners-club-carte-blanche","jcb","maestro","instapayment"]
```
## Related content
- [JSON Path Expressions in the SQL Database Engine](../../relational-databases/json/json-path-expressions-sql-server.md)
- [JSON data in SQL Server](../../relational-databases/json/json-data-sql-server.md)