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
相关产品推荐
相关产品推荐

