You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:10:19