Reputation: 2823
Is that possible to compare two json responses with Jackson lib ignoring all values.
So below will assert both attribute and values.
{
"employee":
{
"id": "1212",
"fullName": "John Miles",
"age": 34
}
}
Code:
ObjectMapper mapper = new ObjectMapper();
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
Upvotes: 0
Views: 227
Reputation: 20185
A quick lookup did not yield any results that Jackson has built-in capabilites for this functionality. We can, however, write our own checker for this task to compare two Map<String, ?>
s in such a way that we return true
iff.:
keySet()
of both Map
s are equalkeySet()
of those objects that are instanceof Map
of both Map
s are equalMap
s must be structurally equally aswell (recursive call)For the analysis, we have to make the assumption that if a Map
is a value in another Map
, it must be a Map<String, ?>
since our solution will make an unchecked cast with this assumption.
With this assumption, a solution may look like this:
@SuppressWarnings("unhecked")
public static boolean areStructuralEqual(Map<String, ?> left, Map<String, ?> right) {
if (!Objects.equals(left.keySet(), right.keySet())) {
return false;
}
Set<String> leftKeysWithMapValues = extractAllKeysThatMapToMaps(left);
Set<String> rightKeysWithMapValues = extractAllKeysThatMapToMaps(right);
if (!Objects.equals(leftKeysWithMapValues, rightKeysWithMapValues)) {
return false;
}
for (String key : leftKeysWithMapValues) {
if (!areStructuralEqual(
(Map<String, ?>) left.get(key),
(Map<String, ?>) right.get(key))) {
return false;
}
}
return true;
}
private static Set<String> extractAllKeysThatMapToMaps(Map<String, ?> map) {
return map.entrySet().stream()
.filter(e -> e.getValue() instanceof Map)
.map(Entry::getKey)
.collect(Collectors.toUnmodifiableSet());
}
Notice that this solution does not verify that the types of the keys are the same. Also, if the value of a key is set to null
in one Map
and the key is not present in the other Map
, the comparison will return false
. The latter can be fixed by filtering out keys whose values are null
:
@SuppressWarnings("unhecked")
public static boolean areStructuralEqual(Map<String, ?> left, Map<String, ?> right) {
Set<Entry<String, ?>> leftEntriesWithNonNullValues =
extractEntriesWithNonNullValues(left);
Set<Entry<String, ?>> rightEntriesWithNonNullValues =
extractEntriesWithNonNullValues(right);
Set<String> leftKeysWithNonNullValues = leftEntriesWithNonNullValues.stream()
.map(Entry::getKey)
.collect(Collectors.toUnmodifiableSet());
Set<String> rightKeysWithNonNullValues = rightEntriesWithNonNullValues.stream()
.map(Entry::getKey)
.collect(Collectors.toUnmodifiableSet());
if (!Objects.equals(leftKeysWithNonNullValues, rightKeysWithNonNullValues)) {
return false;
}
Set<String> leftKeysWithMapValues =
extractAllKeysThatMapToMaps(leftEntriesWithNonNullValues);
Set<String> rightKeysWithMapValues =
extractAllKeysThatMapToMaps(rightEntriesWithNonNullValues);
if (!Objects.equals(leftKeysWithMapValues, rightKeysWithMapValues)) {
return false;
}
for (String key : leftKeysWithMapValues) {
if (!areStructuralEqual(
(Map<String, ?>) left.get(key),
(Map<String, ?>) right.get(key))) {
return false;
}
}
return true;
}
private static Set<String> extractAllKeysThatMapToMaps(Set<Entry<String, ?>> entrySet) {
return entrySet.stream()
.filter(e -> e.getValue() instanceof Map)
.map(Entry::getKey)
.collect(Collectors.toUnmodifiableSet());
}
private static Set<Entry<String, ?>> extractEntriesWithNonNullValues(Map<String, ?> map) {
return map.entrySet().stream()
.filter(e -> Objects.nonNull(e.getValue()))
.collect(Collectors.toUnmodifiableSet());
}
Upvotes: 1