0

This works:

select json_value('{ "a": "b" }', '$.a')

This doesn't work:

select json_value('{ "a": "b" }', '$["a"]')

and neither does this:

select json_value('{ "a": "b" }', '$[''a'']')

In JSON, these are the same:

foo = { "a": "b" }
console.log(foo.a)
console.log(foo["a"])

What am I missing? I get an error trying to use bracket notation in SQL Server:

JSON path is not properly formatted. Unexpected character '"' is found at position 2

2 Answers 2

3

No sooner do I ask, than I stumble on an answer. I couldn't find this in any documentation anywhere, but select json_value('{ "a": "b" }', '$."a"') works. Bracket notation is not supported, but otherwise invalid keys can be escaped with quotation marks, e.g. select json_value('{ "I-m so invalid][": "b" }', '$."I-m so invalid]["') when in JavaScript that would be foo["I-m so invalid]["]

Sign up to request clarification or add additional context in comments.

1 Comment

This part of the documentation (...if the key name starts with a dollar sign or contains special characters such as spaces, surround it with quotes...), explains the use of quotes, so $.a and $."a" are both valid.
1

MsSql reserves this for array index. SQL parses all JSON as a string literal, instead of as an object(JSON or ARRAY) with any hidden key.

Some of what SQL can do will vary with version. Here's a crash course on the annoying (but also really powerful, and fast once in place) requirements. I'm posting more than you need because a lot of the documentation for JSON through MsSql is lacking, and doesn't do justice to how strong it is with JSON.

MsDoc here: https://learn.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server?view=sql-server-ver15

In this example, we are working with a JSON "object" to separate the data into columns. Note how calling a position inside of an array is weird.

    declare @data nvarchar(max) = N'[{"a":"b","c":[{"some":"random","array":"value"},{"another":"random","array":"value"}]},{"e":"f","c":[{"some":"random","array":"value"},{"another":"random","array":"value"}]}]'

--make sure SQL is happy. It will not accept partial snippets    
select ISJSON(@data)
 
 
--let's look at the data in tabular form
select
json1.*
, json2.*
from openjson(@data)
    with    (
            a varchar --note there is no "path" specified here, as "a" is a key in the first layer of the object
            , c nvarchar(max) as JSON --must use "nvarchar(max)" and "as JSON" or SQL freaks out
            , c0 nvarchar(max) N'$.c[0]' as JSON
            ) as json1
cross apply openjson(json1.c) as json2

You can also pull out the individual values, if needed

select oj.value from openjson(@data) as oj where oj.[key] = 1;

select
    oj.value
    , JSON_VALUE(oj.value,N'$.e')
    , JSON_VALUE(oj.value,N'$.c[0].some')
    , JSON_VALUE(@data,N'$[1].c[0].some')       --Similar to your first example, but uses index position instead of key value. Works because SQL views the "[]" brackets as an array while trying to parse.
from openjson(@data) as oj
where oj.[key] = 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.