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

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());
}

关键说明

  1. 基础模式选择:用JSONCompareMode.STRICT作为基础模式,确保items字段默认遵循严格顺序、不可扩展的规则,不需要额外自定义。
  2. 自定义字段规则:针对auths字段单独设置忽略顺序的比较逻辑,同时通过NON_EXTENSIBLE保证数组长度必须一致,符合你的需求。
  3. 规范遵循:自定义比较逻辑必须通过抛出JSONAssertionError来标记不相等的情况,而不是返回布尔值,这是你之前代码报错的核心原因。

内容的提问来源于stack exchange,提问作者yasi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 19:02:53