sqljsonsql-serversql-server-2019

Parse multiple JSON items from a table cell


My table in SQL Server with an nvarchar(max) column holds multiple JSON arrays in each cell. I am trying to parse the 'result' items into separate rows.

JSON array:

[
    {"successful":true,
    "fields":
        [{"index":0, "publicPath": "date"},
        {"index":1, "publicPath": "accountID"},
        {"index":2, "publicPath": "amount"},
        {"index":3, "publicPath": "description"}],
    "result":
        [{"0":2025-07-25",
          "1": "1234",
          "2": "100.00",
          "3": "Some description here"},
         {"0":2025-04-22",
          "1": "4567",
          "2": "12540.00",
          "3": "Some description here"},
         {"0":2025-02-22",
          "1": "1234",
          "2": "700.00",
          "3": "Some description here"}]},
    {"successful":true,
    "fields":
        [{"index":0, "publicPath": "date"},
        {"index":1, "publicPath": "accountID"},
        {"index":2, "publicPath": "amount"},
        {"index":3, "publicPath": "description"}],
    "result":
        [{"0":3025-07-25",
          "1": "2222",
          "2": "2222.00",
          "3": "Some description here"},
         {"0":1025-04-22",
          "1": "4567",
          "2": "88540.00",
          "3": "Some description here"},
         {"0":2025-02-22",
          "1": "1234",
          "2": "700.00",
          "3": "Some description here"}]},
    {"successful":true,
    "fields":
        [{"index":0, "publicPath": "date"},
        {"index":1, "publicPath": "accountID"},
        {"index":2, "publicPath": "amount"},
        {"index":3, "publicPath": "description"}],
    "result":
        [{"0":2025-07-25",
          "1": "1234",
          "2": "100.00",
          "3": "Some description here"},
         {"0":2025-04-22",
          "1": "4567",
          "2": "12540.00",
          "3": "Some description here"},
         {"0":2025-02-22",
          "1": "1234",
          "2": "876.00",
          "3": "Some description here"}
        ]
    }
]

I only care about the result array within the JSON string. Multiple JSON strings are contained in individual cells within table JSONTable in column Data. I've had limited success with:

SELECT
    JSON_Value(x.value, '$.result[*]."0"') AS 'date',
    JSON_Value(x.value, '$.result[*]."1"') AS 'accountID',
    JSON_Value(x.value, '$.result[*]."2"') AS 'amount',
    JSON_Value(x.value, '$.result[*]."3"') AS 'description'
FROM
    [JSONTable] js
CROSS APPLY
    OPENJSON([Data]) AS X

It gets only the last-most result from the JSON table, returning NULL for all other calls and does not segment individual results within each JSON segment into their own rows:

date accountID amount description
NULL NULL NULL NULL
NULL NULL NULL NULL
2025-02-22 1234 876.00 Some description here

It should parse individual results within each of the concatenated calls as well as all of the 'result' fields within each call and split them into their own rows (I am constrained by the JSON structure):

date accountID amount description
2025-07-25 1234 100.00 Some description here
2025-04-22 4567 12540.00 Some description here
2025-02-22 1234 700.00 Some description here
3025-07-25 2222 2222.00 Some description here
1025-04-22 4567 88540.00 Some description here
2025-02-22 1234 700.00 Some description here
2025-07-25 1234 100.00 Some description here
2025-04-22 4567 12540.00 Some description here
2025-02-22 1234 876.00 Some description here

Solution

  • $.result[*] is not a proper JSON path. SQL Server (before 2025) doesn't support wildcards, and if it did it would have no way of returning multiple results in JSON_VALUE anyway.

    You have nested arrays. So you need to feed one OPENJSON into the next using CROSS APPLY.

    SELECT
      j2.*
    FROM
        JSONTable jt
    CROSS APPLY
        OPENJSON(jt.Data)
        WITH (result nvarchar(max) AS JSON) j1
    CROSS APPLY
        OPENJSON(j1.result)
          WITH (
            [date] date '$."0"',
            accountID int '$."1"',
            amount decimal(19,2) '$."2"',
            description nvarchar(100) '$."3"'
        ) j2;
    

    db<>fiddle