25

I am currently able to parse most of a JSON file using SQL Server's OPENJSON WITH (... syntax. However, this particular file contains nested arrays which I do not know how to handle.

Many of the examples I read reference JSON as a variable. In this case I am calling a file:

select DEV_JSON.*
from OPENROWSET
(BULK 'C:\Users\Myuser\Documents\JSON_extract.json', SINGLE_CLOB) as my_datafile
 CROSS APPLY OPENJSON(BulkColumn) 
WITH
  (DOC_ID           varchar(100)  '$.doc._id',
   DOC_REV          varchar(45)   '$.doc._rev',
   DELY_APPL_NAME   varchar(20)   '$.doc.delivery.application',
   DELY_SENT_BY     varchar(25)   '$.doc.delivery.sender.id',
   DELY_SENT_TYPO   varchar(20)   '$.doc.delivery.sender.type',
   .....
   ....
   ...
   ..) as DEV_JSON

One of the attributes contains a nested array. Below I have copied the 1st 5 attributes of my JSON, as well as the nested "recipients" array.

How do I structure my SQL to parse this section?

"doc": {
    "_id": "[email protected]",
    "_rev": "3-e119db13dae8d50ae0c4579ba9c87fc9",
    "delivery": {
        "application": "App_XYZ",
        "sender": {
            "id": "[email protected]",
            "type": "user"
        },
        "recipients": [{
                "type": "email",
                "recipient": "\"Artzer, Daniel J\" <[email protected]>",
                "sentTS": "2017-10-18T13:04:00.133Z"
            },
            {
                "type": "email",
                "recipient": "\"Higgins, Laura L\" <[email protected]>",
                "sentTS": "2017-10-18T13:04:00.133Z"
            },
            {
                "type": "email",
                "recipient": "\"Friedman, Brian\" <[email protected]>",
                "sentTS": "2017-10-18T13:04:00.133Z"
            },
            {
                "type": "email",
                "recipient": "\"Garcia, Charlie M\" <[email protected]>",
                "sentTS": "2017-10-18T13:04:00.133Z"
            }
        ]
    },

2 Answers 2

35

I just had the same problem, and I ended up solving it with multiple CROSS APPLY clauses.

Here's an example of my JSON:

DECLARE @PermsJSON NVARCHAR(MAX) =
N'[{
    "AppId": 1,
    "Perms":
    [{

        "Permission": ["AA", "BB"],
        "PermissionTypeID": 2
    },
    {
        "Permission": ["10"],
        "PermissionTypeID": 1
    }]
},
{
    "AppId": 2,
    "Perms":
    [{

        "Permission": ["IM", "NM"],
        "PermissionTypeID": 2
    },
    {
        "Permission": ["42"],
        "PermissionTypeID": 1
    }]
}]';

And then I can parse it using the following query:

SELECT
    a.AppId
    ,[Permission] = c.Value
    ,b.PermissionTypeID
FROM
    OPENJSON(@PermsJSON)
    WITH
        (
            AppId INT N'$.AppId'
            ,Perms NVARCHAR(MAX) AS JSON
        ) AS a
CROSS APPLY
    OPENJSON(a.Perms)
    WITH
        (
            PermissionTypeID INT
            ,[Permission] NVARCHAR(MAX) AS JSON
        ) AS b
CROSS APPLY OPENJSON(b.Permission) AS c;

The results then look like this:

AppId   Permission  PermissionTypeID
1       AA          2
1       BB          2
1       10          1
2       IM          2
2       NM          2
2       42          1
Sign up to request clarification or add additional context in comments.

2 Comments

the answer I was looking for
its very important to use "AS JSON" for the node with array inside!
11

After MUCH searching I finally discovered the answer to this issue. I simply have to include the Nested Array as another JSON column in my query, like:

WITH
 (DOC_ID                varchar(100)  '$.doc._id',
  DOC_REV               varchar(45)   '$.doc._rev',
  DELY_APPL_NAME        varchar(20)   '$.doc.delivery.application',
  DELY_SENT_BY          varchar(25)   '$.doc.delivery.sender.id',
  DELY_SENT_TYPO        varchar(20)   '$.doc.delivery.sender.type',
  RECIPS                nvarchar(max) '$.doc.delivery.recipients' as JSON,
  PAYLOAD_START_TIME    varchar(30)   '$.doc.payload.startTS',
  ....
  ...
  ..
  ) as my_query

So, I end up with one record per JSON document, with (in this case) a varchar column containing JSON text.

Next, I can run a separate query on this column to parse the JSON and create a "child table" associated with the Parent.

1 Comment

You can use another CROSS APPLY OPENJSON on the JSON column RECIPS, if you want all the data in a single table. See my answer for an example.

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.