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

JSONAssert如何将int 5与double 5.0视为相同及金额字符串匹配方案

JSONAssert 自定义比较器解决数值字符串匹配问题

问题场景

有两个以Java String表示的JSON对象:

  • 预期JSON:
{"id" : "1234567","balance" : "123"}
  • 实际JSON:
{"id" : "1234567","balance" : "123.00"}

使用JSONAssert.assertEquals("incorrect json", actual, expected, false);校验时,因balance字段预期值为"123"、实际值为"123.00"导致校验失败。需要实现自定义比较器,让这类数值型字符串(包括整数与浮点数形式的数值字符串)视为相等,且无需排除该属性。

解决方案

实现自定义数值字符串比较器

通过继承JSONAssert的DefaultComparator,重写字段值比较逻辑:尝试将字符串转换为BigDecimal进行数值比较,转换失败则回退到默认字符串比较。

代码示例:

import org.json.JSONException;
import org.json.JSONObject;
import org.skyscreamer.jsonassert.comparator.DefaultComparator;

import java.math.BigDecimal;

public class NumericStringComparator extends DefaultComparator {
    @Override
    public void compareValues(String prefix, Object expected, Object actual, JSONObject expectedObj, JSONObject actualObj) throws JSONException {
        // 仅处理字符串类型的数值比较
        if (expected instanceof String && actual instanceof String) {
            try {
                BigDecimal expectedNum = new BigDecimal((String) expected);
                BigDecimal actualNum = new BigDecimal((String) actual);
                if (expectedNum.compareTo(actualNum) == 0) {
                    return; // 数值相等,直接通过校验
                }
            } catch (NumberFormatException e) {
                // 转换失败,走默认字符串比较逻辑
            }
        }
        // 非数值字符串或转换失败时,使用默认比较逻辑
        super.compareValues(prefix, expected, actual, expectedObj, actualObj);
    }
}

使用自定义比较器校验

方式1:全局应用自定义比较器

对所有字段启用数值字符串匹配逻辑:

String expected = "{\"id\" : \"1234567\",\"balance\" : \"123\"}";
String actual = "{\"id\" : \"1234567\",\"balance\" : \"123.00\"}";

JSONAssert.assertEquals("incorrect json", expected, actual, new NumericStringComparator());

方式2:仅对指定字段应用

如果只需要对balance字段启用该逻辑,可使用Customization:

import org.skyscreamer.jsonassert.Customization;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;

import java.math.BigDecimal;

String expected = "{\"id\" : \"1234567\",\"balance\" : \"123\"}";
String actual = "{\"id\" : \"1234567\",\"balance\" : \"123.00\"}";

Customization balanceCustomization = new Customization("balance", (expectedVal, actualVal) -> {
    if (expectedVal instanceof String && actualVal instanceof String) {
        try {
            BigDecimal expectedNum = new BigDecimal((String) expectedVal);
            BigDecimal actualNum = new BigDecimal((String) actualVal);
            return expectedNum.compareTo(actualNum) == 0;
        } catch (NumberFormatException e) {
            return expectedVal.equals(actualVal);
        }
    }
    return expectedVal.equals(actualVal);
});

JSONAssert.assertEquals("incorrect json", expected, actual, JSONCompareMode.STRICT, balanceCustomization);

关于int与double的匹配说明

JSONAssert默认的DefaultComparator对原生数值类型(非字符串包裹的数值),比如预期5(int)和实际5.0(double),会自动转换为BigDecimal后比较,因此默认就能视为相等。但你的场景是数值被包裹在字符串中,所以需要自定义比较器实现类似逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:33:37