When using JSON with SQL Server, you can use the JSON_VALUE()
function to return a scalar value from a JSON string.
To use this function, you provide two arguments; the JSON expression, and the property to extract.
Syntax
The syntax goes like this:
JSON_VALUE ( expression , path )
Where expression
is the JSON string expression, and path
is the property you want to extract from that expression.
The path argument can include an optional path mode component. This optional path mode can be a value of either lax
or strict
. This value, if any, comes before the dollar sign.
Example 1 – Basic Usage
Here’s an example to demonstrate basic usage of the JSON_VALUE()
function.
SELECT JSON_VALUE('{"Name": "Bruce"}', '$.Name') AS 'Result';
Result:
+----------+ | Result | |----------| | Bruce | +----------+
In this example:
- The
{"Name": "Bruce"}
argument is the JSON expression (a small one, but still a valid JSON expression). JSON expressions consist of a key/value pair. In this case,Name
is the key,Bruce
is its value. - The
$.Name
argument is the path. This path references the value of theName
key of the JSON expression. So we can extract the value by referencing the name of the pair.
Example 2 – Arrays
To extract a value from an array, reference its index within square brackets, followed by the relevant key. Here’s an example:
/* CREATE THE ARRAY (and put into a variable called @data) */ DECLARE @data NVARCHAR(4000) SET @data=N'{ "Cities": [ { "Name": "Kabul", "CountryCode": "AFG", "District": "Kabol", "Population": 1780000 }, { "Name": "Qandahar", "CountryCode": "AFG", "District": "Qandahar", "Population": 237500 } ] }' /* QUERY THE ARRAY */ SELECT JSON_VALUE(@data,'$.Cities[0].Name') AS 'Name', JSON_VALUE(@data,'$.Cities[0].CountryCode') AS 'Country Code', JSON_VALUE(@data,'$.Cities[0].District') AS 'District', JSON_VALUE(@data,'$.Cities[0].Population') AS 'Population' UNION ALL SELECT JSON_VALUE(@data,'$.Cities[1].Name') AS 'Name', JSON_VALUE(@data,'$.Cities[1].CountryCode') AS 'Country Code', JSON_VALUE(@data,'$.Cities[1].District') AS 'District', JSON_VALUE(@data,'$.Cities[1].Population') AS 'Population';
Result:
+----------+----------------+------------+--------------+ | Name | Country Code | District | Population | |----------+----------------+------------+--------------| | Kabul | AFG | Kabol | 1780000 | | Qandahar | AFG | Qandahar | 237500 | +----------+----------------+------------+--------------+
So in this example, we create a JSON array and put it into a variable called @data
. We then run a query, using @data
as the first argument of the JSON_VALUE()
function (this is because @data
contains the JSON expression).
Arrays use zero-based numbering, so to extract the first item we need to use Cities[0]
, the second one Cities[1]
, and so on.
Example 3 – A Database Example
If we were to put the data from the previous example into a database, we could rewrite the query as follows:
SELECT JSON_VALUE(Document,'$.Cities[0].Name') AS 'Name', JSON_VALUE(Document,'$.Cities[0].CountryCode') AS 'Country Code', JSON_VALUE(Document,'$.Cities[0].District') AS 'District', JSON_VALUE(Document,'$.Cities[0].Population') AS 'Population' FROM Json_Documents UNION ALL SELECT JSON_VALUE(Document,'$.Cities[1].Name') AS 'Name', JSON_VALUE(Document,'$.Cities[1].CountryCode') AS 'Country Code', JSON_VALUE(Document,'$.Cities[1].District') AS 'District', JSON_VALUE(Document,'$.Cities[1].Population') AS 'Population' FROM Json_Documents
Result:
+----------+----------------+------------+--------------+ | Name | Country Code | District | Population | |----------+----------------+------------+--------------| | Kabul | AFG | Kabol | 1780000 | | Qandahar | AFG | Qandahar | 237500 | +----------+----------------+------------+--------------+
This assumes that the JSON document is stored in a column called Document
, which is in a table called Json_Documents
.
Example 4 – Path Mode
As mentioned, you also have the option of specifying the path mode. This can be either lax
or strict
.
The value of the path mode determines what happens when the path expression contains an error. Specifically:
- In lax mode, the function returns empty values if the path expression contains an error. For example, if you request the value $.name, and the JSON text doesn’t contain a name key, the function returns null, but does not raise an error.
-
In strict mode, the function raises an error if the path expression contains an error.
The default value is lax
.
Here’s an example to demonstrate the difference between these two modes.
Error in lax mode
Here’s what happens when the path expression contains an error while in lax mode.
SELECT JSON_VALUE('{"Name": "Bruce"}', 'lax $.Hobbies') AS 'Result';
Result:
+----------+ | Result | |----------| | NULL | +----------+
In this example we’re trying to reference Hobbies
, but that key doesn’t exist in the JSON document. In this case we get a null value (because we’re using lax mode).
Error in strict mode
Here’s what happens when we run the same code in strict mode.
SELECT JSON_VALUE('{"Name": "Bruce"}', 'strict $.Hobbies') AS 'Result';
Result:
Msg 13608, Level 16, State 1, Line 1 Property cannot be found on the specified JSON path.
As expected, strict mode results in an error message being displayed.
Example 5 – Returning Objects and Arrays
The JSON_VALUE()
function doesn’t return objects and arrays. If you want to return an object or an array, use the JSON_QUERY()
function instead. Here’s an example where I use both functions within a query.
DECLARE @data NVARCHAR(4000) SET @data=N'{ "Suspect": { "Name": "Homer Simpson", "Address": { "City": "Mae Sai", "Province": "Chiang Rai", "Country": "Thailand" }, "Hobbies": ["Eating", "Sleeping", "Base Jumping"] } }' SELECT JSON_VALUE(@data,'$.Suspect.Name') AS 'Name', JSON_VALUE(@data,'$.Suspect.Address.Country') AS 'Country', JSON_QUERY(@data,'$.Suspect.Hobbies') AS 'Hobbies', JSON_VALUE(@data,'$.Suspect.Hobbies[2]') AS 'Last Hobby';
Result:
+---------------+-----------+----------------------------------------+--------------+ | Name | Country | Hobbies | Last Hobby | |---------------+-----------+----------------------------------------+--------------| | Homer Simpson | Thailand | ["Eating", "Sleeping", "Base Jumping"] | Base Jumping | +---------------+-----------+----------------------------------------+--------------+
In this case, I use JSON_VALUE()
to return various scalar values, and JSON_QUERY()
to return an array.
So if you need to return an object or an array (including the whole JSON document), see JSON_QUERY()
Examples in SQL Server.