JSONAssert特定字段忽略顺序的比较实现报错求助
解决JSONAssert中混合数组比较模式的问题
问题场景
你需要比较两个JSON字符串,其中:
items数组要求严格匹配顺序且不可扩展(STRICT模式)auths数组要求忽略顺序但不可扩展(NON_EXTENSIBLE模式)
待比较的JSON如下:
StringA
{"items": ["SfWn8eQ", "QiOiJrw", "2Npc2Nv"], "auths": ["5895c0a1-0fa9-4222-bbfb-5f96f6737cd7", "415499a6-daa3-45b7-b967-83aa94a38da1", "5d572399-a2ae-4bc4-b989-e2115028612e"]}
StringB
{"items": ["SfWn8eQ", "QiOiJrw", "2Npc2Nv"], "auths": ["415499a6-daa3-45b7-b967-83aa94a38da1", "5d572399-a2ae-4bc4-b989-e2115028612e", "5895c0a1-0fa9-4222-bbfb-5f96f6737cd7"]}
你之前的代码报错,核心问题在于自定义比较函数的写法不符合JSONAssert规范——框架要求自定义比较逻辑不是通过返回布尔值判断,而是通过抛出JSONAssertionError表示不相等,正常返回则表示相等。
正确解决方案
这里提供两种可行的写法,都能满足你的需求:
方案1:使用内置的ArrayValueMatcher(推荐)
JSONAssert内置了ArrayValueMatcher,可以直接实现忽略数组顺序的比较,无需自己写排序逻辑:
import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONException; import org.skyscreamer.jsonassert.comparator.CustomComparator; import org.skyscreamer.jsonassert.comparator.Customization; import org.skyscreamer.jsonassert.comparator.ArrayValueMatcher; import static org.junit.Assert.fail; // 对auths字段应用忽略顺序的数组匹配器,模式用NON_EXTENSIBLE保证不可扩展 Customization authsCustomization = new Customization( "auths", new ArrayValueMatcher<>(JSONCompareMode.NON_EXTENSIBLE) ); // 基础比较模式用STRICT,确保items字段严格顺序、不可扩展 CustomComparator comparator = new CustomComparator( JSONCompareMode.STRICT, authsCustomization ); try { JSONAssert.assertEquals(expected, actual, comparator); } catch (JSONException e) { fail("JSON比较失败: " + e.getMessage()); }
方案2:自定义比较逻辑
如果你需要更灵活的控制,可以自己实现排序比较,但要遵循JSONAssert的规范:
import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONException; import org.skyscreamer.jsonassert.comparator.CustomComparator; import org.skyscreamer.jsonassert.comparator.Customization; import org.skyscreamer.jsonassert.comparator.JSONAssertionError; import java.util.Collections; import java.util.List; import static org.junit.Assert.fail; // 自定义auths字段的比较逻辑 Customization authsCustomization = new Customization("auths", (o1, o2) -> { // 先校验类型是否为数组 if (!(o1 instanceof List) || !(o2 instanceof List)) { throw new JSONAssertionError("auths字段必须是数组类型"); } List<String> list1 = (List<String>) o1; List<String> list2 = (List<String>) o2; // 校验数组长度一致(不可扩展的要求) if (list1.size() != list2.size()) { throw new JSONAssertionError("auths数组长度不匹配"); } // 排序后比较内容 Collections.sort(list1); Collections.sort(list2); if (!list1.equals(list2)) { throw new JSONAssertionError("auths数组内容不匹配(忽略顺序)"); } }); CustomComparator comparator = new CustomComparator(JSONCompareMode.STRICT, authsCustomization); try { JSONAssert.assertEquals(expected, actual, comparator); } catch (JSONException e) { fail("JSON比较失败: " + e.getMessage()); }
关键说明
- 基础模式选择:用
JSONCompareMode.STRICT作为基础模式,确保items字段默认遵循严格顺序、不可扩展的规则,不需要额外自定义。 - 自定义字段规则:针对
auths字段单独设置忽略顺序的比较逻辑,同时通过NON_EXTENSIBLE保证数组长度必须一致,符合你的需求。 - 规范遵循:自定义比较逻辑必须通过抛出
JSONAssertionError来标记不相等的情况,而不是返回布尔值,这是你之前代码报错的核心原因。
内容的提问来源于stack exchange,提问作者yasi
相关产品推荐
相关产品推荐

