判断JSON对象是否被包含的方法存在数组元素匹配逻辑bug
修复JSON对象包含判断中的数组元素交叉误判问题
原方法的核心缺陷在于:将数组内对象的属性值孤立提取,破坏了单个数组元素内部的属性关联关系。只要第二个JSON中存在所有离散的属性值(不管这些值属于哪个数组元素),就会误判为包含,这就是坐标值交叉时误判的原因。
基于「待比较JSON结构始终相同」的前提,我们可以通过递归层级校验的方式修复这个问题,确保每个数组元素作为整体参与匹配,而不是拆分属性。修复后的代码如下:
using Newtonsoft.Json.Linq; public static partial class JsonOperations { public static bool IsIncludedIn(this JObject first, JObject second) { return IsTokenIncluded(first, second); } private static bool IsTokenIncluded(JToken firstToken, JToken secondToken) { // 类型不同直接不匹配 if (firstToken.Type != secondToken.Type) return false; switch (firstToken.Type) { case JTokenType.Object: var firstObj = (JObject)firstToken; var secondObj = (JObject)secondToken; // 遍历第一个对象的所有属性,递归校验是否都被包含 foreach (var prop in firstObj.Properties()) { if (!secondObj.TryGetValue(prop.Name, out var secondPropValue) || !IsTokenIncluded(prop.Value, secondPropValue)) { return false; } } return true; case JTokenType.Array: var firstArray = (JArray)firstToken; var secondArray = (JArray)secondToken; // 遍历第一个数组的每个元素,检查第二个数组中是否存在完全匹配的元素 foreach (var firstItem in firstArray) { bool foundMatch = false; foreach (var secondItem in secondArray) { if (IsTokenIncluded(firstItem, secondItem)) { foundMatch = true; break; } } if (!foundMatch) return false; } return true; case JTokenType.Value: // 直接比较值是否相等 return JToken.DeepEquals(firstToken, secondToken); default: // 其他类型(如Comment、Undefined等)按结构不匹配处理 return false; } } }
修复逻辑说明
- 递归层级校验:从根对象开始,逐层校验每个节点的类型和内容
- 对象处理:遍历第一个对象的所有属性,确保第二个对象存在对应属性且属性值满足包含关系
- 数组处理:将每个数组元素作为整体校验,确保第一个数组的每个元素,在第二个数组中能找到完全匹配的元素(属性值完全对应)
- 值类型处理:直接比较值的相等性,保证基础类型的匹配准确
针对你给出的坐标交叉反例,修复后的方法会正确返回false:第一个数组中的{"lat":-32.364,"lng":158.207}在第二个数组中找不到完全匹配的元素,因此判定为不包含。
内容的提问来源于stack exchange,提问作者Szyszka947
相关产品推荐
相关产品推荐

