C#中无法正确比对两个JSON,多变更场景下报错求助
JSON差异对比与提取需求(C#实现)
我有两个JSON字符串,分别为left(原始JSON)和right(编辑后JSON)。需要找出两者的差异,并生成仅包含变更内容及指定键“ID”和“TYPE”的新JSON。尝试在C#中使用JsonDiffPatchDotNet和JsonDiffer包,但未能实现需求,寻求解决方案。
引用的包
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using JsonDiffPatchDotNet; using JsonDiffer;
JSON压缩代码
public static string Minify(string json) { if (json == null) { throw new ArgumentNullException(nameof(json)); } return Regex.Replace(json, "(\"(?:[^\\\"]|\\.)*\")|\\s+", "$1"); }
主逻辑代码
public static void Main(string[] args) { string Tleft = @"{ ""TEST JSON"" : ""JSON"", ""JSON"":{ ""ANIMALS"":[ { ""ID"":0, ""TYPE"":""DOG"", ""DOG"":{ ""TYPE"":""RETRIEVER"", ""RETRIEVER"":{ ""NAME"":""LEO"", ""AGE"":3, ""YEARS"":[2019 , 2020, 2021], ""WEIGHTS"": [2,10,13] } }, ""REMARKS"":{ ""ID"":1, ""STATUS"":""GOOD"", ""REFERENCE"": { ""SOURCE"": ""XYZ"", ""FIT"": 1, ""BMI"" : 1 } } }, { ""ID"":1, ""TYPE"":""DOG2"", ""DOG2"":{ ""TYPE"":""PUG"", ""RETRIEVER"":{ ""NAME"":""HUTCH"", ""AGE"":4, ""YEARS"":[2019 , 2020, 2021, 2022], ""WEIGHTS"": [2,3,4,4] } }, ""REMARKS"":{ ""ID"":1, ""TYPE"" : ""REFERENCE"", ""STATUS"":""GOOD"", ""REFERENCE"": { ""SOURCE"": ""XYZ"", ""FIT"": 1, ""BMI"" : 1 } } }, { ""ID"": 2, ""TYPE"": ""DIAGNOSTICS"", ""STATUS"": ""ENABLED"" }, { ""ID"": 3, ""TYPE"": ""ORGANISATION"", ""ORGANISATION"":{ ""NAME"":""RED CROSS"", ""YEAR"": 2023 } } ] } }"; string Tright = @"{ ""TEST JSON"" : ""JSON"", ""JSON"":{ ""ANIMALS"":[ { ""ID"":0, ""TYPE"":""DOG"", ""DOG"":{ ""TYPE"":""RETRIEVER"", ""RETRIEVER"":{ ""NAME"":""LEO"", ""AGE"":3, ""YEARS"":[2019 , 2020, 2021], ""WEIGHTS"": [2,10,13] } }, ""REMARKS"":{ ""ID"":1, ""STATUS"":""GOOD"", ""REFERENCE"": { ""SOURCE"": ""XYZ"", ""FIT"": 1, ""BMI"" : 1 } } }, { ""ID"":1, ""TYPE"":""DOG2"", ""DOG2"":{ ""TYPE"":""PUG"", ""RETRIEVER"":{ ""NAME"":""HUTCH"", ""AGE"":4, ""YEARS"":[2019 , 2020, 2021, 2022], ""WEIGHTS"": [2,3,4,4] } }, ""REMARKS"":{ ""ID"":1, ""TYPE"" : ""REFERENCE"", ""STATUS"":""GOOD"", ""REFERENCE"": { ""SOURCE"": ""XYZ"", ""FIT"": 1, ""BMI"" : 1 } } }, { ""ID"": 2, ""TYPE"": ""DIAGNOSTICS"", ""STATUS"": ""ENABLED ZZZ"" }, { ""ID"": 3, ""TYPE"": ""ORGANISATION"", ""ORGANISATION"":{ ""NAME"":""RED CROSS ZZZ"", ""YEAR"": 2023 } } ] } }"; var left = JToken.Parse(Minify(Tleft)); var right = JToken.Parse(Minify(Tright)); var jdp = new JsonDiffPatch(); // 使用JsonDiffPatchDotNet包生成差异 var diff2 = JsonDifferentiator.Differentiate(left, right, OutputMode.Symbol, showOriginalValues: true); Console.WriteLine("--------------------------------------"); Console.WriteLine("----diff using JsonDiffPatchDotNet----"); Console.WriteLine("--------------------------------------"); Console.WriteLine(diff2); Console.WriteLine("***************************************"); Console.WriteLine("***************************************\n\n"); if (diff2 != null) { // 移除差异结果中的*字符 var formatedDiff = JToken.Parse(diff2.ToString().Replace("*", "")); // 应用补丁 // 当变更超过3个不同索引时会报错 var Diff2PatchOutput = jdp.Patch(left, formatedDiff).ToString(); Console.WriteLine("--------------------------------------"); Console.WriteLine("---------- CURRENT OUTPUT --------"); Console.WriteLine("--------------------------------------"); Console.WriteLine(Diff2PatchOutput); Console.WriteLine("***************************************"); Console.WriteLine("***************************************\n\n"); } else { Console.WriteLine("Diff failed or Invalid json inputs left and rigth !"); } }
当前输出
-------------------------------------- ----diff using JsonDiffPatchDotNet---- -------------------------------------- { "*JSON": { "*ANIMALS": [ { "*STATUS": "ENABLED ZZZ" }, { "*ORGANISATION": { "*NAME": "RED CROSS ZZZ" } } ] } } *************************************** *************************************** -------------------------------------- ---------- CURRENT OUTPUT -------- -------------------------------------- { "TEST JSON": "JSON", "JSON": { "ANIMALS": { "ORGANISATION": { "NAME": "RED CROSS ZZZ" } } } } *************************************** ***************************************
期望输出
-------------------------------------- ---------- EXPECTED OUTPUT -------- -------------------------------------- { "TEST JSON": "JSON", "JSON": { "ANIMALS": [ { "ID": 2, "TYPE": "DIAGNOSTICS", "STATUS": "ENABLED ZZZ" }, { "ID": 3, "TYPE": "ORGANISATION", "ORGANISATION": { "NAME": "RED CROSS ZZZ" } } ] } } *************************************** ***************************************
存在的问题
- 当变更发生在JSON数组的不同索引中时,第一个变更会被忽略;
- 当变更超过3个不同索引时,抛出错误:
System.IO.InvalidDataException HResult = 0x80131501 Message = Invalid patch object Source = JsonDiffPatchDotNet StackTrace: at JsonDiffPatchDotNet.JsonDiffPatch.Patch(JToken left, JToken patch) at JsonDiffPatchDotNet.JsonDiffPatch.ObjectPatch(JObject obj, JObject patch) at JsonDiffPatchDotNet.JsonDiffPatch.Patch(JToken left, JToken patch) at JsonDiffPatchDotNet.JsonDiffPatch.ObjectPatch(JObject obj, JObject patch) at JsonDiffPatchDotNet.JsonDiffPatch.Patch(JToken left, JToken patch)
欢迎提出其他实现思路。
内容的提问来源于stack exchange,提问作者DeLorean
相关产品推荐
相关产品推荐

