1

Say I have two JSON strings as follows:

[{"RowId":102787,"UserId":1,"Activity":"This is another test","Timestamp":"2017-11-25T14:37:30.3700000"}]

[{"RowId":102787,"UserId":2,"Activity":"Testing the Update function","Timestamp":"2017-11-25T14:37:30.3700000"}]

Both have the same properties but two of the properties in the second string have different values than the first (UserId and Activity). Is it possible, in Azure SQL Database T-SQL, to generate a third JSON string that contains the values in the second string that are different from the first? In other words, I'd like a string returned that looks like this:

[{"UserId":2,"Activity":"Testing the Update function"}]

Also, the solution should assume that the properties in the JSON strings are not known. I need this to be a generic solution for any two JSON strings.

Randy Minder
  • 47,200
  • 49
  • 204
  • 358

1 Answers1

3

Have not tried this on Azure, but it seems to work on SQL Server 2017 There is probably a more elegant way to get to the final JSON string other than through string manipulation, perhaps we can update the answer as better ways are found.

-- Expected : [{"UserId":2,"Activity":"Testing the Update function"}]
DECLARE  @jsonA     NVARCHAR(MAX) = '[{"RowId":102787,"UserId":1,"Activity":"This is another test","Timestamp":"2017-11-25T14:37:30.3700000"}]'
        ,@jsonB     NVARCHAR(MAX) = '[{"RowId":102787,"UserId":2,"Activity":"Testing the Update function","Timestamp":"2017-11-25T14:37:30.3700000"}]'
        ,@result    NVARCHAR(MAX) = ''

SELECT   @jsonA = REPLACE(REPLACE(@jsonA, ']', ''), '[', '')
        ,@jsonB = REPLACE(REPLACE(@jsonB, ']', ''), '[', '')

;WITH DSA AS
(
    SELECT *
    FROM OPENJSON(@jsonA)   
)
,DSB AS
(
    SELECT *
    FROM OPENJSON(@jsonB)   
)
SELECT @result  += CONCAT   (
                                 '"', B.[key], '":'
                                ,IIF(B.[type] = 2, B.[value], CONCAT('"', B.[value], '"'))  -- havent checked types other than 1 and 2; think there's a bool type?
                                ,','
                            )

FROM DSA    A
JOIN DSB    B ON A.[key] = B.[key]
WHERE A.[value] != B.[value]

SELECT CONCAT('[{', LEFT(@result, LEN(@result) - 1), '}]')
MarkD
  • 5,276
  • 1
  • 14
  • 22
  • Thank you. Very nice piece of work, and this works under Azure. I don't understand the nuances of JSON that well. What do you mean with your comment, "havent checked types other than 1 and 2; think there's a bool type?" – Randy Minder Nov 26 '17 at 12:15
  • @RandyMinder; the types in JSON for numeric or string determine whether or not the value will be offered in quotes or not. I think that JSON, because of its root in javascript, may have a 3rd type: boolean. Just saying that I have not coded for any eventuality other than string and numeric. Hope that clears things up :) – MarkD Nov 27 '17 at 09:46
  • Got it. I did a bit of research over the weekend, and a bit of tweeking of your code and got it working the way I need to. Thanks for your help. – Randy Minder Nov 27 '17 at 16:55
  • @RandyMinder - good to hear! If there are any improvements that you have made that may benefit others - feel free to share. – MarkD Nov 27 '17 at 17:48
  • @MarkD [{"RowId":102787,"UserId":1,"Activity":"This is another test","Timestamp":"2017-11-25T14:37:30.3700000","a":[{"b":"sssss"},{"b":"dfdfdf"}]}] how to compare this string using this SP – Kasunjith Bimal Sep 02 '19 at 07:17