json-diff icon indicating copy to clipboard operation
json-diff copied to clipboard

Ignore difference between null or empty array

Open paulux84 opened this issue 2 years ago • 2 comments

Can be usefull to add a the possibility in LenientJsonArrayPartialMatcher to ignore difference between null array, array field not exist or empty array. So this three example become the same

{
    name: "example"
    array : null
}
{
    name: "example"
    array : []
}
{
    name: "example"
}

paulux84 avatar Nov 09 '23 12:11 paulux84

Hi @paulux84,

I need a little bit refactoring on the library to be able to implement this feature easily, But you can already do something to manage the comparison between [] and null. You can implement your own JsonMatcher to replace the default CompositeJsonMatcher, you can write something like that:

public class AdvancedJsonArrayMatcher implements JsonMatcher {
    private final PartialJsonMatcher<ArrayNode> jsonArrayPartialMatcher;
    private final PartialJsonMatcher<ObjectNode> jsonObjectPartialMatcher;
    private final PartialJsonMatcher<ValueNode> primitivePartialMatcher;

    public AdvancedJsonArrayMatcher(
            PartialJsonMatcher<ArrayNode> jsonArrayPartialMatcher,
            PartialJsonMatcher<ObjectNode> jsonObjectPartialMatcher,
            PartialJsonMatcher<ValueNode> primitivePartialMatcher
    ) {
        this.jsonArrayPartialMatcher = jsonArrayPartialMatcher;
        this.jsonObjectPartialMatcher = jsonObjectPartialMatcher;
        this.primitivePartialMatcher = primitivePartialMatcher;
    }

    @Override
    public JsonDiff diff(Path path, JsonNode expected, JsonNode received) {
        // check comparison between array and null values
        if (
                (expected.isEmpty() && received.isNull())
                || (received.isEmpty() && expected.isNull())
        ) {
            return new MatchedPrimaryDiff(path, expected);
        }

        // default JsonMatcher code
        if (expected instanceof ObjectNode  && received instanceof ObjectNode) {
            return this.jsonObjectPartialMatcher.jsonDiff(path, (ObjectNode) expected, (ObjectNode) received, this);
        } else if (expected instanceof ArrayNode && received instanceof ArrayNode) {
            return this.jsonArrayPartialMatcher.jsonDiff(path, (ArrayNode) expected, (ArrayNode) received, this);
        } else if (expected instanceof ValueNode && received instanceof ValueNode){
            return this.primitivePartialMatcher.jsonDiff(path, (ValueNode) expected, (ValueNode) received, this);
        } else {
            return new UnMatchedPrimaryDiff(path, expected, received);
        }
    }
}

And you this class like you use the CompositeJsonMatcher. For the case: actual

{
    name: "example"
    array : []
}

and expected

{
    name: "example"
}

This case il already covered by the LenientJsonObjectPartialMatcher, since it ignore extra values.

To avoid to be able to implement custom JsonMatcher I need to rewrite the PartialJsonMatcher since for now this interface allow to compare two values with the same type, but null and [] don't have the same type.

deblockt avatar Nov 10 '23 07:11 deblockt

Seems not working...i have nested arrays and are not working

paulux84 avatar Nov 16 '23 12:11 paulux84