AllIsWell AllIsWell - 4 months ago 16
JSON Question

How to skip a node in json comparision

I have a json comparator

class JSONUtils {

public static void areEqual(def context_1, def context_2) {
Object obj1,obj2;
Object json = new JSONTokener(context_1).nextValue();
if (json instanceof JSONObject) {
obj1 = new JSONObject(context_1);
obj2 = new JSONObject(context_2);
} else if (json instanceof JSONArray) {
obj1 = new JSONArray(context_1);
obj2 = new JSONArray(context_2);
}
def ObjectMapper mapper = new ObjectMapper();
def JsonNode tree1 = mapper.readTree(obj1.toString());
def JsonNode tree2 = mapper.readTree(obj2.toString());
assert tree1.equals(tree2);
}
}


Which works fine when two json are exactly same. I have a special case where I need to skip or ignore two node values while comparison.

Example:

First Json:
{
"rd":12,
"td":"text1"
"dt": 123456,
"vt": "west"
}
Second Json:
{
"rd":12,
"td":"text1"
"dt": 333333,
"vt": "east"
}


I need to ignore or skip the "dt" and "vt" comparison.

How can I implement it.

Answer

Create a custom POJO to hold the values you care about:

// Ignore fields "dt" and "vt"
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyType {
    // Ideally these should use getters/setters
    public int rd;
    public String td;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof MyType) {
            MyType t = (MyType)obj;
            return t.rd == this.rd
                    && Objects.equals(t.td, this.td);
        }
        return false;
    }

    // hashCode() should always be overriden alongside equals()
    @Override
    public int hashCode() {
        return Objects.hash(rd, td);
    }
}

In your code you can construct and compare them like this:

ObjectMapper mapper = new ObjectMapper();
MyType t1 = mapper.readValue(obj1.toString(), MyType.class);
MyType t2 = mapper.readValue(obj2.toString(), MyType.class);
assert t1.equals(t2);

Per our discussion in the comments, here's a generic solution to compare any two JSON objects, while filtering out any set of keys, using the Guava library:

public static boolean jsonEquals(String json1, String json2, String... ignoreKeys) throws IOException {
    // this is a Guava Predicate
    Predicate<String> filter = Predicates.not(Predicates.in(Sets.newHashSet(ignoreKeys)));

    ObjectMapper mapper = new ObjectMapper();
    Map<String, Object> object1 = Maps.filterKeys(mapper.readValue(json1, Map.class), filter);
    Map<String, Object> object2 = Maps.filterKeys(mapper.readValue(json2, Map.class), filter);
    return object1.equals(object2);
}