Home > Mobile >  Update an existing JSON Value inside JSON array
Update an existing JSON Value inside JSON array

Time:08-02

DECLARE @jsontable TABLE (JsonData nvarchar(max) NULL)

DECLARE @JsonData NVARCHAR(MAX) = N'
{
  "Sections": {
    "SectionType": false,
    "SectionName": "Section1"
  },
  "MultiOptions": [
    {
      "Customers": {
        "CustomerName": "name1",
        "Address": "",
        "Source1" : "1"
      },
      "Orders": {
        "OrderName": "item1",
        "Qty": 1,
        "Dest1" : "0",
        "PurchasedQty" : "0"
      },
      "IsMainOption": true
    },
    {
      "Customers": {
        "CustomerName": "name2",
        "Address": "",
        "Source1" : "2"
      },
      "Orders": {
        "OrderName": "item2",
        "Qty": 2,
        "Dest1" : "0",
        "PurchasedQty" : "0"
      },
      "IsMainOption": false
    },
    {
      "Customers": {
        "CustomerName": "name3",
        "Address": "",
        "Source1" : "3"
      },
      "Orders": {
        "OrderName": "item2",
        "Qty": 3,
        "Dest1" : "0",
        "PurchasedQty" : "0"
      },
      "IsMainOption": false
    }
  ],
  "DateUpdated": "2022-05-24",
  "WhoUpdated": 1
}'

INSERT INTO @jsontable
    SELECT @JsonData

;WITH cte AS 
(
    SELECT 
        MultiOptions.[key] AS MultiOptionsKey,
        MultiOptionsCustomers.[key] AS MultiOptionsCustomersKey,
        MultiOptionsCustomers.[value] AS MultiOptionsCustomersValue,
        MultiOptionsOrders.[key] AS MultiOptionsOrdersKey,
        MultiOptionsOrders.[value] AS MultiOptionsOrdersValue,
        JsonData 
    FROM
        @jsontable a 
    CROSS APPLY 
        OPENJSON(JsonData, '$.MultiOptions') MultiOptions
    CROSS APPLY 
        OPENJSON(MultiOptions.value, '$.Customers') MultiOptionsCustomers
    CROSS APPLY 
        OPENJSON(MultiOptions.value, '$.Orders' ) AS MultiOptionsOrders 
)
UPDATE cte 
SET JsonData = JSON_MODIFY(JsonData, '$.MultiOptions['   MultiOptionsKey   '].Customers['   MultiOptionsCustomersKey   '].Orders['   MultiOptionsOrdersKey   '].PurchasedQty', 'Qty#Value')
--select * from cte;

I'm getting this error:

The argument 2 of the "JSON_MODIFY" must be a string literal.

when I execute this query.

I need to update below for all items inside array:

UPDATE [MultiOptions.Orders.Dest1] = [MultiOptions.Customers.Source1]
UPDATE [MultiOptions.Customers.PurchasedQty] = [MultiOptions.Customers.Qty]

CodePudding user response:

I don't think you can use wild cards to modify the JSON content. In your case a possible solution is to parse the stored JSON content (using OPENJSON()) and rebuild the JSON again (uisng FOR JSON PATH):

UPDATE @jsontable
SET JsonData = JSON_MODIFY(
   JsonData,
   '$.MultiOptions',
   (
      SELECT 
      CustomerName AS [Customers.CustomerName],
      Address AS [Customers.Address], 
      Source1 AS [Customers.Source1], 
      OrderName AS [Orders.OrderName], 
      Qty AS [Orders.Qty], 
      Source1 AS [Orders.Dest1],      -- updated value
      Qty AS [Orders.PurchasedQty],   -- updated value
      IsMainOption AS [IsMainOption]
   FROM OPENJSON(JsonData, '$.MultiOptions') WITH (
      CustomerName nvarchar(max) '$.Customers.CustomerName', 
      Address nvarchar(max) '$.Customers.Address', 
      Source1 nvarchar(max) '$.Customers.Source1', 
      OrderName nvarchar(max) '$.Orders.OrderName', 
      Qty int '$.Orders.Qty', 
      IsMainOption bit '$.IsMainOption'
   )
   FOR JSON PATH  
   )
)

CodePudding user response:

You don't necessarily have to rebuild the whole JSON. In your case, because you only have one level of arrays to feed through OPENJSON, you can just rebuild that, and use JSON_VALUE and JSON_MODIFY to access the various values.

Unfortunately, SQL Server does not have JSON_AGG. So to aggregate whole JSON objects you need STRING_AGG to aggregate, and also JSON_QUERY to prevent double-escaping


UPDATE t
SET JsonData =
  JSON_MODIFY(
    JsonData,
    '$.MultiOptions',
    JSON_QUERY((
        SELECT
          '['   STRING_AGG(
            JSON_MODIFY(
              JSON_MODIFY(
                arr.value,
                '$.Orders.Dest1',
                JSON_VALUE(arr.value, '$.Customers.Source1')
              ),
              '$.Customers.PurchasedQty',
              JSON_VALUE(arr.value, '$.Customers.Qty')
            ),
            ','
          )   ']'
        FROM OPENJSON(t.JsonData, '$.MultiOptions') arr
    ))
  )
FROM jsontable t;

SQL Fiddle

  • Related