Compare dois objetos JSON com Jackson
1. Visão geral
Neste artigo, veremos como comparar dois objetos JSON usandoJackson - uma biblioteca de processamento JSON para Java.
2. Dependência do Maven
Primeiro, vamos adicionar a dependênciajackson-databind Maven:
com.fasterxml.jackson.core
jackson-databind
2.9.8
3. Usando Jackson para comparar dois objetos JSON
Estaremos usando a classeObjectMapper para ler um objeto como umJsonNode.
Vamos criar umObjectMapper:
ObjectMapper mapper = new ObjectMapper();
3.1. Compare dois objetos JSON simples
Vamos começar usando o métodoJsonNode.equals. The equals() method performs a full (deep) comparison.
Suponha que temos uma string JSON definida como a variávels1:
{
"employee":
{
"id": "1212",
"fullName": "John Miles",
"age": 34
}
}
E queremos compará-lo com outro JSON,s2:
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles"
}
}
Vamos ler o JSON de entrada comoJsonNodee comparar:
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
É importante observar queeven though the order of attributes in input JSON variables s1 and s2 is not the same, the equals() method ignores the order and treats them as equal.
3.2. Compare dois objetos JSON com um elemento aninhado
A seguir, veremos como comparar dois objetos JSON com elementos aninhados.
Vamos começar com um JSON definido como a variávels1:
{
"employee":
{
"id": "1212",
"fullName":"John Miles",
"age": 34,
"contact":
{
"email": "[email protected]",
"phone": "9999999999"
}
}
}
Como podemos ver, o JSON contém um elemento aninhadocontact. Queremos compará-lo com outro JSON definido pors2:
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles",
"contact":
{
"email": "[email protected]",
"phone": "9999999999"
}
}
}
Vamos ler o JSON de entrada comoJsonNodee comparar:
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
Novamente, devemos notar queequals() can also compare two input JSON objects with nested elements.
3.3. Compare dois objetos JSON contendo um elemento de lista
Da mesma forma, também podemos comparar dois objetos JSON que contêm um elemento de lista.
Vamos considerar este JSON definido comos1:
{
"employee":
{
"id": "1212",
"fullName": "John Miles",
"age": 34,
"skills": ["Java", "C++", "Python"]
}
}
Estamos comparando com outro JSONs2:
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles",
"skills": ["Java", "C++", "Python"]
}
}
Vamos ler o JSON de entrada comoJsonNodee comparar:
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
É importante saber quetwo list elements are only compared as equal if they have the same values in the exact same order.
4. Compare dois objetos JSON com um comparador personalizado
JsonNode.equals funciona muito bem na maioria dos casos. Jackson também forneceJsonNode.equals(comparator, JsonNode) para configurar um objeto Java Comparator personalizado. Vamos entender como usar umComparator personalizado.
4.1. Comparador personalizado para comparar valores numéricos
Vamos entender como usar umComparator personalizado para comparar dois elementos JSON com valores numéricos.
Usaremos este JSON como entradas1:
{
"name": "John",
"score": 5.0
}
Vamos comparar com outro JSON definido comos2:
{
"name": "John",
"score": 5
}
Precisamos observar quethe values of attribute score in inputs s1 and s2 are not the same.
Vamos ler o JSON de entrada comoJsonNodee comparar:
JsonNode actualObj1 = mapper.readTree(s1);
JsonNode actualObj2 = mapper.readTree(s2);
assertNotEquals(actualObj1, actualObj2);
Como podemos notar, os dois objetos não são iguais. O método padrãoequals() considera os valores 5,0 e 5 como diferentes.
No entanto,we can use a custom Comparator to compare values 5 and 5.0 and treat them as equal.
Vamos primeiro criar umComparator para comparar dois objetosNumericNode:
public class NumericNodeComparator implements Comparator
{
@Override
public int compare(JsonNode o1, JsonNode o2)
{
if (o1.equals(o2)){
return 0;
}
if ((o1 instanceof NumericNode) && (o2 instanceof NumericNode)){
Double d1 = ((NumericNode) o1).asDouble();
Double d2 = ((NumericNode) o2).asDouble();
if (d1.compareTo(d2) == 0) {
return 0;
}
}
return 1;
}
}
A seguir, vamos ver como usar esteComparator:
NumericNodeComparator cmp = new NumericNodeComparator();
assertTrue(actualObj1.equals(cmp, actualObj2));
4.2. Comparador personalizado para comparar valores de texto
Vamos ver outroexample of a custom Comparator for a case-insensitive comparison de dois valores JSON.
Usaremos este JSON como entradas1:
{
"name": "john",
"score": 5
}
Vamos comparar com outro JSON definido comos2:
{
"name": "JOHN",
"score": 5
}
Como podemos ver, o atributoname está em minúsculas na entradas1e maiúsculas ems2.
Vamos primeiro criar umComparator para comparar dois objetosTextNode:
public class TextNodeComparator implements Comparator
{
@Override
public int compare(JsonNode o1, JsonNode o2) {
if (o1.equals(o2)) {
return 0;
}
if ((o1 instanceof TextNode) && (o2 instanceof TextNode)) {
String s1 = ((TextNode) o1).asText();
String s2 = ((TextNode) o2).asText();
if (s1.equalsIgnoreCase(s2)) {
return 0;
}
}
return 1;
}
}
Vamos ver como comparars1 es2 usandoTextNodeComparator:
JsonNode actualObj1 = mapper.readTree(s1);
JsonNode actualObj2 = mapper.readTree(s2);
TextNodeComparator cmp = new TextNodeComparator();
assertNotEquals(actualObj1, actualObj2);
assertTrue(actualObj1.equals(cmp, actualObj2));
Por fim, podemos ver o uso de um objeto comparador personalizado ao comparar dois objetos JSONcan be very useful when the input JSON element value is not exactly the same but we still want to treat them as equal.
5. Conclusão
Neste tutorial rápido, vimos como usar Jackson para comparar dois objetos JSON e usar um comparador personalizado.
Claro, como sempre, o código-fonte completo de todos os exemplos discutidos aqui pode ser encontradoover on GitHub.