C#实现JSON版Except方法遇数组异常,求排查及替代方案
实现JSON的Except功能遇到问题
我熟悉C#的Except()方法,它会从第一个集合中移除存在于第二个集合中的元素。我需要为JSON实现类似的逻辑,于是写了如下代码:
public static JsonDocument Except(this JsonDocument firstJson, JsonDocument secondJson) { if (firstJson.RootElement.ValueKind != secondJson.RootElement.ValueKind) throw new JsonException($"The '{nameof(firstJson)}' and '{nameof(secondJson)}' must be the same kind of value"); switch (firstJson.RootElement.ValueKind) { case JsonValueKind.Object: var result = JsonNode.Parse("{}")!; var firstJsonProperties = firstJson.RootElement.EnumerateObject(); foreach (var firstJsonProperty in firstJsonProperties) { if (!secondJson.RootElement.TryGetProperty(firstJsonProperty.Name, out JsonElement secondJsonPropertyValue) || secondJsonPropertyValue.ValueKind != firstJsonProperty.Value.ValueKind) { result[firstJsonProperty.Name] = firstJsonProperty.Value.AsNode(); continue; } else if (firstJsonProperty.Value.ValueKind == JsonValueKind.Object) { var objectExceptionResult = Except(firstJsonProperty.Value.ToJsonDocument(), secondJsonPropertyValue.ToJsonDocument()); if (objectExceptionResult.RootElement.AsNode()!.AsObject().Any()) result[firstJsonProperty.Name] = objectExceptionResult.RootElement.AsNode(); } else if (firstJsonProperty.Value.ValueKind == JsonValueKind.Array) { var arrayExceptionResult = Except(firstJsonProperty.Value.ToJsonDocument(), secondJsonPropertyValue.ToJsonDocument()); if (arrayExceptionResult.RootElement.AsNode()!.AsArray().Any()) result[firstJsonProperty.Name] = arrayExceptionResult.RootElement.AsNode(); } } return result.ToJsonDocument(); case JsonValueKind.Array: var result2 = new JsonArray(); var firstJsonElements = firstJson.RootElement.EnumerateArray(); var secondJsonElements = secondJson.RootElement.EnumerateArray(); foreach (var firstJsonElement in firstJsonElements) { foreach (var secondJsonElement in secondJsonElements) { if (firstJsonElement.ValueKind != secondJsonElement.ValueKind) continue; if (firstJsonElement.ValueKind == JsonValueKind.Object || firstJsonElement.ValueKind == JsonValueKind.Array) { var exceptionResult = Except(firstJsonElement.ToJsonDocument(), secondJsonElement.ToJsonDocument()); if (!firstJsonElement.IsEquivalentTo(exceptionResult.RootElement)) { if (exceptionResult.RootElement.AsNode()!.AsObject().Any()) result2.Add(exceptionResult); break; } else if (secondJsonElement.IsEquivalentTo(secondJsonElements.Last())) { result2.Add(firstJsonElement); } } } if (firstJsonElement.ValueKind != JsonValueKind.Object && firstJsonElement.ValueKind != JsonValueKind.Array && !secondJsonElements.Any(p => p.ToString() == firstJsonElement.ToString())) result2.Add(firstJsonElement); } return result2.ToJsonDocument(); default: if (!firstJson.RootElement.IsEquivalentTo(secondJson.RootElement)) return firstJson; break; } return firstJson; }
问题现象
这段代码处理简单JSON时表现正常,但当两个JSON均为数组且第一个数组元素数量少于第二个时,无法正确移除所有匹配元素。
测试用例
var firstJson = JsonDocument.Parse(@"{ ""x"":""haha"", ""a"":{ ""z"":1, ""b"":3 }, ""haff"": [ 1, 2, { ""a"": 4, ""b"": 5 } ] }"); var secondJson = JsonDocument.Parse(@"{ ""x"": 1024, ""b"":""afa"", ""a"":{ ""z"":3, ""a"":4 }, ""haff"": [ 1, 2, { ""a"": 5 } ] }");
预期功能
- 若属性为简单类型(字符串、整数等),在第二个JSON中存在则删除该属性
- 若属性为数组,移除第一个数组中存在于第二个对应数组的所有元素
- 若属性为对象,移除第一个对象中存在于第二个对应对象的所有属性
- 若数组或对象内容被清空,需删除整个数组或对象
求助需求
我目前已经使用Json.More.Net NuGet包,希望得到:
- 现有代码的问题原因排查
- 具备该功能的现成NuGet包推荐
内容的提问来源于stack exchange,提问作者Szyszka947
相关产品推荐
相关产品推荐

