I'm trying to parse a specific, valid JSON string from a column to its individual values using T-SQL.
I have looked at many of the samples, particularly this one Parse JSON in TSQL and still am not quite there. Can anyone suggest a valid T-SQL statement that will do the job?
Sample cte with json in column MessageDetail:
select Id, MessageDetail from cte_example
Id  MessageDetail
1   {"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance", "sysadmins": {"sysadmin": {"Member": "DummyAdmin", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-22T18:10:55.023", "Removed": "2019-07-22T19:21:15.867"}}}
T-SQL I'm trying to use:
select
    json_value(b.value, '$.Member') as Member
    ,json_value(b.value, '$.IsDisabled') as IsDisabled
    ,json_value(b.value, '$.IsNTGroup') as IsNTGroup
    ,json_value(b.value, '$.Added') as Added
    ,json_value(b.value, '$.Removed') as Removed
from
    cte_example a
    outer apply openjson(json_query(a.MessageDetail, '$.sysadmins.sysadmin')) b
Which results in the below error:
Msg 13609, Level 16, State 2, Line 17 JSON text is not properly formatted. Unexpected character 'D' is found at position 0.
Which I find confusing as the JSON query $.sysadmins.sysadmin is valid. What am I doing wrong?
Note: I have this query working correctly when it attempts to parse the below
{"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance", "sysadmins": {"sysadmin": [{"Member": "sa", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-19T03:01:49.677"}, {"Member": "testuser", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-19T03:01:49.677"}, {"Member": "abc\\User1", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-19T03:01:49.677"}, {"Member": "NT SERVICE\\SQLWriter", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-19T03:01:49.677"}, {"Member": "NT SERVICE\\Winmgmt", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-19T03:01:49.677"}, {"Member": "NT Service\\MSSQLSERVER", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-19T03:01:49.677"}, {"Member": "NT SERVICE\\SQLSERVERAGENT", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-19T03:01:49.677"}, {"Member": "DummyAdmin", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-22T02:10:07.833", "Removed": "2019-07-22T03:00:02.177"}, {"Member": "domain1\\testservice", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-19T04:18:51.900"}, {"Member": "##MS_PolicyEventProcessingLogin##", "IsDisabled": "1", "IsNTGroup": "0", "Added": "2019-07-22T04:07:48.497"}]}}
                Solution 1:
If you want to use JSON_VALUE, what you need in this situation is to use OPENJSON with explicit schema and AS JSON option in a column definition. The path argument here is $.sysadmins:
Table:
CREATE TABLE cte_example (
   Id int,
   MessageDetail nvarchar(max)
)
INSERT INTO cte_example
   (Id, MessageDetail)
VALUES   
   (1, N'{"@xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance", "sysadmins": {"sysadmin": {"Member": "DummyAdmin", "IsDisabled": "0", "IsNTGroup": "0", "Added": "2019-07-22T18:10:55.023", "Removed": "2019-07-22T19:21:15.867"}}}')
Statement:
SELECT 
   JSON_VALUE(b.sysadmin, '$.Member') AS Member,
   JSON_VALUE(b.sysadmin, '$.IsDisabled') AS IsDisabled,
   JSON_VALUE(b.sysadmin, '$.IsNTGroup') AS IsNTGroup,
   JSON_VALUE(b.sysadmin, '$.Added') AS Added,
   JSON_VALUE(b.sysadmin, '$.Removed') AS Removed
FROM cte_example a
OUTER APPLY OPENJSON(a.MessageDetail, '$.sysadmins') WITH (
   sysadmin nvarchar(max) '$.sysadmin' AS JSON
) b
Output:
-------------------------------------------------------------------
Member      IsDisabled  IsNTGroup   Added                   Removed
-------------------------------------------------------------------
DummyAdmin  0           0           2019-07-22T18:10:55.023 2019-07-22T19:21:15.867
Solution 2:
You may try with another approach, without JSON_VALUE, again using OPENJSON with explicit schema definition. The path argument here is $.sysadmins.sysadmin:
SELECT b.*
FROM cte_example a
OUTER APPLY OPENJSON(a.MessageDetail, '$.sysadmins.sysadmin') WITH (
   Member nvarchar(10) '$.Member', 
   IsDisabled nvarchar(1) '$.IsDisabled', 
   IsNTGroup nvarchar(1) '$.IsNTGroup', 
   Added nvarchar(23) '$.Added', 
   Removed nvarchar(23) '$.Removed'
) b
Explanations about your error:
With statement:
select
    b.*
from
    cte_example a
    outer apply openjson(json_query(a.MessageDetail, '$.sysadmins.sysadmin')) b
your results are:
---------------------
key value   type 
---------------------
Member      DummyAdmin              1
IsDisabled  0                       1
IsNTGroup   0                       1
Added       2019-07-22T18:10:55.023 1
Removed     2019-07-22T19:21:15.867 1
Values in value column is not in JSON format and json_value(b.value, '$.Member') returns an error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With