Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update a specific item of an array in json object

I'm manipulating a JSON column in a SQL Azure table/database, the JSON object is formed like this:

{
  "statusId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
  "creationDateTime": "",
  "assignations": [
    {
      "userId": "CA3B0589-B558-4FCC-93A6-560754D324FC",
      "dateTime": "",
      "isCurrentAssigned": false
    },
    {
      "userId": "CA3B0589-B558-4FCC-93A6-560754D325E8",
      "dateTime": "",
      "isCurrentAssigned": false
    },
    {
      "userId": "CA3B0589-B558-4FCC-93A6-560754D347N",
      "dateTime": "",
      "isCurrentAssigned": true
    }
  ]
}

What I want to accomplish is to find a specific element inside the array "assignations" and then update some of its properties, just something like:

UPDATE MyTable
SET JsonData = JSON_MODIFY(JsonData, '$.assignations.isCurrentAssigned', CONVERT(BIT, 0))
FROM MyDb
WHERE JSON_VALUE(JsonData, '$.assignations.isCurrentAssigned') = CONVERT(BIT, 1) AND
JSON_VALUE(JsonData, '$.assignations.userId') =  CONVERT(UNIQUEIDENTIFIER, 'CA3B0589-B558-4FCC-93A6-560754D347N')

Of course this T-SQL is not working, I will appreciate any help on this

like image 825
Anon Dev Avatar asked Dec 12 '16 12:12

Anon Dev


People also ask

How do I change an object's value in an array of objects?

To change the value of an object in an array:Call the findIndex() method to get the index of the specific object. Access the array at the index and change the property's value using dot notation. The value of the object in the array will get updated in place.

How do I change the value of a JSON object?

Array value of a JSON object can be modified. It can be simply done by modifying the value present at a given index. Note: If value is modified at an index which is out of the array size, then the new modification will not replace anything in the original information but rather will be an add-on.

How do you change an array in JSON?

Approach 1: First convert the JSON string to the JavaScript object using JSON. Parse() method and then take out the values of the object and push them into the array using push() method.

How to update an array of objects in JavaScript?

JavaScript offers two ways to update the object, using map () and findIndex (). This built-in array method, provided by JavaScript, iterates over the original array and creates the new array, completing the elements based on the specified conditions. Instead of an arrow function, you can also pass the callback function.

How to modify an array value of a JSON object in JavaScript?

How to modify an array value of a JSON object in JavaScript? Modifying an array is just like modifying an object when that array is inside the object. The normal general principles will apply here. In the following example, Initially in the ' companies ' array, the first element is ' Tesla'.

How do you add an object to an existing array?

So let's take a look at how we can add objects to an already existing array. To add an object at the first position, use Array.unshift. To add an object at the last position, use Array.push. To add an object in the middle, use Array.splice. This function is very handy as it can also remove items.

How to change a specific element in an array?

In addition, I use a series of variables to change a certain element, the process is more cumbersome, there may be a better way, but you could refer to this method first: The general idea is to manually add an index to the array, then change the array element corresponding to the specified index, empty the previous array, and add the new element.


2 Answers

I've found a "simple workaround" to handle this, maybe it is not the best solution but I need a quick solution and this is working.

Basically I convert the array to a T-SQL Table, update the records on that table as desired, then convert that table to a JSON Array and with that array I replace the original one.

Sample code:

DECLARE @SomeJSON NVARCHAR(MAX) = 
'{
  "statusId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
  "creationDateTime": "abc",
  "assignations": [
    {
      "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
      "creationDateTime": "",
      "isCurrentAssigned": false
    },
    {
      "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
      "creationDateTime": "",
      "isCurrentAssigned": false
    },
    {
      "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
      "creationDateTime": "",
      "isCurrentAssigned": true
    }
  ]
}'


DECLARE @TblAssignations TABLE
(
userId UNIQUEIDENTIFIER NULL,
creationDateTime DATETIME NULL,
isCurrentAssigned BIT NULL
)

INSERT INTO @TblAssignations
SELECT *
FROM OPENJSON(@SomeJSON, '$.assignations')
WITH(userId UNIQUEIDENTIFIER, creationDateTime DATETIME, isCurrentAssigned BIT)

UPDATE @TblAssignations
SET isCurrentAssigned = 0
WHERE userId = '5A5BC717-F33A-42A5-8E48-99531C30EC87' AND
isCurrentAssigned = 1

INSERT INTO @TblAssignations
VALUES
(
'5A5BC717-F33A-42A5-8E48-99531C30EC87',
'',
1
)

DECLARE @NewParentAssignations NVARCHAR(MAX) = (SELECT * FROM @TblAssignations FOR JSON PATH)

SET @SomeJSON = JSON_MODIFY(@SomeJSON, '$.assignations', JSON_QUERY(@NewParentAssignations))

SELECT @SomeJSON
like image 92
Anon Dev Avatar answered Nov 18 '22 05:11

Anon Dev


We have to do something similar at work, and ended up with a similar approach to the one you ended up with, although we do the processing directly while reading the JSON, to avoid using a temp table or a table var.

  DECLARE @SomeJSON NVARCHAR(MAX) = 
    '{
      "statusId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
      "creationDateTime": "abc",
      "assignations": [
        {
          "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
          "creationDateTime": "",
          "isCurrentAssigned": false
        },
        {
          "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
          "creationDateTime": "",
          "isCurrentAssigned": false
        },
        {
          "userId": "5A5BC717-F33A-42A5-8E48-99531C30EC87",
          "creationDateTime": "",
          "isCurrentAssigned": true
        }
      ]
    }'

    DECLARE @NewParentAssignations NVARCHAR(MAX) = (
        SELECT * 
        FROM (

            SELECT --the update is done with the CASE clause
                userId, 
                creationDateTime,
                CASE WHEN userId = '5A5BC717-F33A-42A5-8E48-99531C30EC87' AND isCurrentAssigned = 1
                     THEN CAST (0 AS BIT)
                     ELSE isCurrentAssigned
                END AS isCurrentAssigned
            FROM OPENJSON(@SomeJSON, '$.assignations')
            WITH(userId UNIQUEIDENTIFIER, creationDateTime DATETIME, isCurrentAssigned BIT)

            UNION ALL -- the insert is done using UNION ALL

            SELECT '5A5BC717-F33A-42A5-8E48-99531C30EC87' AS userId, '' AS creationDateTime, CAST (1 AS BIT) AS isCurrentAssigned 

        ) Result
        FOR JSON PATH
    )


    SET @SomeJSON = JSON_MODIFY(@SomeJSON, '$.assignations', JSON_QUERY(@NewParentAssignations))

    SELECT @SomeJSON

At the end this yields the same result.

like image 30
D33 Avatar answered Nov 18 '22 06:11

D33