Search code examples
javajunitjacksonjsonassert

How to write a json custom comparator for a specific datatype using skyscreamer (JSONAssert)?


How do I write a JSONCustomComparator not for a specific field, but a specific datatype?

I know for a specific field, I can do,

CustomComparator comparator = new CustomComparator(
            JSONCompareMode.LENIENT,
            new Customization("field.nunber", (o1, o2) -> true),
            new Customization("field.code", (o1, o2) -> true));
JSONAssert.assertEquals(expectedJsonAsString, actualJsonAsString, comparator);

But how do I do it for a specific datatype? E.g. I have to compare Boolean and Int(true with 1, false with 0),

 ValueMatcher<Object> BOOL_MATCHER = new ValueMatcher<Object>() {
    @Override
    public boolean equal(Object o1, Object o2) {
        if (o1.toString().equals("true") && o2.toString().equals("1")) {
            return true;
        } else if (o1.toString().equals("false") && o2.toString().equals("0")) {
            return true;
        } else if (o2.toString().equals("true") && o1.toString().equals("1")) {
            return true;
        } else if (o2.toString().equals("false") && o1.toString().equals("0")) {
            return true;
        }
        return JSONCompare.compareJSON(o1.toString(), o2.toString(), JSONCompareMode.LENIENT).passed();
    }
};
CustomComparator comparator = new CustomComparator(JSONCompareMode.LENIENT, new Customization("*", BOOL_COMPARATOR));

But this doesn't seem to be the best way, also the BOOL_MATCHER will only return boolean, not the JSONCompareResult, so that the diff can be shown.

Is there a better way to do this?


Solution

  • Create a new custom Comparator by extending the DefaultComparator.

    private static class BooleanCustomComparator extends DefaultComparator {
        public BooleanCustomComparator(final JSONCompareMode mode) {
            super(mode);
        }
        @Override
        public void compareValues(String prefix, Object expectedValue, Object actualValue, JSONCompareResult result)
                throws JSONException {
            if (expectedValue instanceof Number && actualValue instanceof Boolean) {
                if (BooleanUtils.toInteger((boolean)actualValue) != ((Number) expectedValue).intValue()) {
                    result.fail(prefix, expectedValue, actualValue);
                }
            } else if (expectedValue instanceof Boolean && actualValue instanceof Number) {
                if (BooleanUtils.toInteger((boolean)expectedValue) != ((Number) actualValue).intValue()) {
                    result.fail(prefix, expectedValue, actualValue);
                }
            } else {
                super.compareValues(prefix, expectedValue, actualValue, result);
            }
        }
    }
    

    Usage:

    JSONAssert.assertEquals(expectedJson, actualJson, new BooleanCustomComparator(JSONCompareMode.STRICT));