JSONAssert fails due to order mismatch even with JSONCompareMode=LENIENT

838 Views Asked by At

I'm using the JSONAssert library to compare two JSON arrays.

The arrays to be compared look like this:

actual

{"components": [
          {
            "createdAt": "2022-03-03T10:22:01.959148348Z",
            "createdBy": "abc",
            "category": "category-1",
            "uuid": "469ba1b0-5975-49a0-8fa9-4f3ae5436c68"
          },
          {
            "createdAt": "2022-03-03T10:22:01.959152770Z",
            "createdBy": "def",
            "category": "category-2",
            "uuid": "494e0510-c322-4a45-a103-227b5a3a0adc"
          }]
}

expected

{"components": [
          {
            "createdAt": "2022-03-02T06:58:18.532605787Z",
            "createdBy": "def",
            "category": "category-2",
            "uuid": "78846bb4-5721-447b-ba8b-7fe91bc125a5"
          },
          {
            "createdAt": "2022-03-02T06:58:18.532613344Z",
            "createdBy": "abc",
            "category": "category-1",
            "uuid": "dfe61f6b-addf-442a-8f7c-6e3f249cb4be"
          }]
}

Here's the code.

ObjectMapper objectMapper = new ObjectMapper();
        try {
            JSONObject actual = new JSONObject(objectMapper.writeValueAsString(actualEntity.getObj())); // actualEntity and expectedEntity are deserialized with Jackson 
            JSONObject expected = new JSONObject(objectMapper.writeValueAsString(expectedEntity.getObj()));
            ArrayValueMatcher<Object> arrValMatch = new ArrayValueMatcher<>(new CustomComparator(
                    JSONCompareMode.LENIENT,
                    new Customization("components[*].createdAt", (o1, o2) -> true),
                    new Customization("components[*].uuid", (o1, o2) -> true)));
            Customization arrayValueMatchCustomization = new Customization("components", arrValMatch);
            CustomComparator customArrayValueComparator = new CustomComparator(
                    JSONCompareMode.LENIENT,
                    arrayValueMatchCustomization);
            JSONAssert.assertEquals(expected.toString(), actual.toString(), customArrayValueComparator);
        } catch (JsonProcessingException | JSONException e) {
            Assert.fail("Something went wrong while parsing JSON: " + e.getMessage());
        }

Here is the error:

java.lang.AssertionError: components[0].category
Expected: category-2
     got: category-1
 ; components[0].createdBy
Expected: def
     got: abc
 ; components[1].category
Expected: category-1
     got: category-2
 ; components[1].createdBy
Expected: abc
     got: def

I don't understand why the comparison fails here when it should actually pass with the LENIENT compare mode.

1

There are 1 best solutions below

0
On

Since I did not find a solution to the problem mentioned in the OP, I ended up using another library for this, it is called json-unit-assertj.

My code works and looks like this now.

import net.javacrumbs.jsonunit.core.Option;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;

String actualComponents = objectMapper.writeValueAsString(actualEntity.getComponents());
String expectedComponents = objectMapper.writeValueAsString(expectedEntity.getComponents());
assertThatJson(actualComponents)
         .when(Option.IGNORING_ARRAY_ORDER)
         .whenIgnoringPaths("[*].createdAt", "[*].uuid")
         .isArray()
         .isEqualTo(expectedComponents);

PS: I'm not marking this as an accepted answer since it does not really answer the question in the OP.