J. Jonah Jameson
J. Jonah Jameson

Reputation: 11

Extracting the values of a nested array in JSON using SQL Server

I'm trying to extract the values of a nested array inside JSON in SQL Server but not sure how. I know how to extract JSON items and also how to extract arrays but haven't been able to get the nested array out values. I found one example that supposedly shows how to do this but haven't been able to get it to work.

Here's an example: The following JSON falls under a field called json_data. There is an array under 'order', called 'line_items'. Each item in 'line_items' has multiple fields: 'quantity', 'name', 'total_money', etc.

Extracting the top level variables: 'order', 'id' is easy. But not sure how to go about extracting all the variables under the array 'line_items': specifically, 'quantity', 'name', 'total_money'. I would be grateful for any help. Many thanks!

{'order': {'location_id': 'NYC',
'id': '123',
'source': {'name': 'Kurtz'},
'line_items': [{'quantity': '1',
'name': 'Item1',
'note': 'No notes',
'base_price_money': {'amount': 1000, 'currency': 'USD'},
'total_discount_money': {'amount': 0, 'currency': 'USD'},
'total_money': {'amount': 1000, 'currency': 'USD'}},
{'quantity': '1',
'name': 'Item2',
'note': '',
'base_price_money': {'amount': 400, 'currency': 'USD'},
'gross_sales_money': {'amount': 400, 'currency': 'USD'},
'total_tax_money': {'amount': 0, 'currency': 'USD'},
'total_discount_money': {'amount': 0, 'currency': 'USD'},
'total_money': {'amount': 400, 'currency': 'USD'}}],
'total_money': {'amount': 1400, 'currency': 'USD'},
'total_tax_money': {'amount': 0, 'currency': 'USD'},
'total_discount_money': {'amount': 0, 'currency': 'USD'}},
'location': {'name': 'Breakfast Club',
'address': 'Buena Vista road',
'phone': '555-555-5155'}}

Upvotes: 0

Views: 2828

Answers (2)

Yitzhak Khabinsky
Yitzhak Khabinsky

Reputation: 22177

Assuming that you have SQL Server 2016 or later.

SQL

DECLARE @json NVARCHAR(MAX) = 
N'{
    "order": {
        "location_id": "NYC",
        "id": "123",
        "source": {
            "name": "Kurtz"
        },
        "line_items": [
            {
                "quantity": "1",
                "name": "Item1",
                "note": "No notes",
                "base_price_money": {
                    "amount": 1000,
                    "currency": "USD"
                },
                "total_discount_money": {
                    "amount": 0,
                    "currency": "USD"
                },
                "total_money": {
                    "amount": 1000,
                    "currency": "USD"
                }
            },
            {
                "quantity": "1",
                "name": "Item2",
                "note": "",
                "base_price_money": {
                    "amount": 400,
                    "currency": "USD"
                },
                "gross_sales_money": {
                    "amount": 400,
                    "currency": "USD"
                },
                "total_tax_money": {
                    "amount": 0,
                    "currency": "USD"
                },
                "total_discount_money": {
                    "amount": 0,
                    "currency": "USD"
                },
                "total_money": {
                    "amount": 400,
                    "currency": "USD"
                }
            }
        ],
        "total_money": {
            "amount": 1400,
            "currency": "USD"
        },
        "total_tax_money": {
            "amount": 0,
            "currency": "USD"
        },
        "total_discount_money": {
            "amount": 0,
            "currency": "USD"
        }
    },
    "location": {
        "name": "Breakfast Club",
        "address": "Buena Vista road",
        "phone": "555-555-5155"
    }
}';

--SELECT ISJSON(@json);

SELECT --parent.*
    parent.id, parent.[location_id], parent.[source]
   , child.*
FROM OPENJSON(@json, '$.order') 
WITH
(
   id      INT         '$.id',
   [location_id]   VARCHAR(30) '$.location_id',
   [source]   VARCHAR(30) '$.source.name',
   [line_items]   NVARCHAR(MAX) AS JSON
)
AS parent
CROSS APPLY OPENJSON(parent.[line_items])
WITH
(
   quantity         INT         '$.quantity',
   [name]           VARCHAR(50) '$.name',
   [note]           VARCHAR(50) '$.note',
   [base_price_money.amount]            VARCHAR(50) '$.base_price_money.amount',
   [base_price_money.currency]          VARCHAR(50) '$.base_price_money.currency'
) AS child;

Output

+-----+-------------+--------+----------+-------+----------+-------------------------+---------------------------+
| id  | location_id | source | quantity | name  |   note   | base_price_money.amount | base_price_money.currency |
+-----+-------------+--------+----------+-------+----------+-------------------------+---------------------------+
| 123 | NYC         | Kurtz  |        1 | Item1 | No notes |                    1000 | USD                       |
| 123 | NYC         | Kurtz  |        1 | Item2 |          |                     400 | USD                       |
+-----+-------------+--------+----------+-------+----------+-------------------------+---------------------------+

Upvotes: 2

lptr
lptr

Reputation: 6788

declare @j nvarchar(max) = N'{"order": {"location_id": "NYC",
"id": "123",
"source": {"name": "Kurtz"},
"line_items": [{"quantity": "1",
"name": "Item1",
"note": "No notes",
"base_price_money": {"amount": 1000, "currency": "USD"},
"total_discount_money": {"amount": 0, "currency": "USD"},
"total_money": {"amount": 1000, "currency": "USD"}},
{"quantity": "2",
"name": "Item2",
"note": "",
"base_price_money": {"amount": 400, "currency": "USD"},
"gross_sales_money": {"amount": 400, "currency": "USD"},
"total_tax_money": {"amount": 0, "currency": "USD"},
"total_discount_money": {"amount": 0, "currency": "USD"},
"total_money": {"amount": 400, "currency": "USD"}}],
"total_money": {"amount": 1400, "currency": "USD"},
"total_tax_money": {"amount": 0, "currency": "USD"},
"total_discount_money": {"amount": 0, "currency": "USD"}},
"location": {"name": "Breakfast Club",
"address": "Buena Vista road",
"phone": "555-555-5155"}}';


select *
from openjson(@j, '$.order.line_items')
with
(
--..adjust datatypes..
quantity int,
name nvarchar(50),
note nvarchar(50),
basepriceamount money '$.base_price_money.amount',
basepricecurrency nvarchar(10) '$.base_price_money.currency',
totaldiscountamount money '$.total_discount_money.amount',
totaldiscountcurrency nvarchar(10) '$.total_discount_money.currency',
totalmoneyamount money '$.total_money.amount',
totalmoneycurrency nvarchar(10) '$.total_money.currency'
);

Upvotes: 1

Related Questions