2つのJSONオブジェクトをJacksonと比較する
1. 概要
In this tutorial, we’ll have a look at comparing two JSON objects using Jackson — a JSON processing library for Java.
2. Mavenの依存関係
まず、 jackson-databindMavenの依存関係を追加しましょう。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
3. Jacksonを使用して2つのJSONオブジェクトを比較する
We’ll be using the ObjectMapper class to read an object as a JsonNode.
ObjectMapperを作成しましょう。
ObjectMapper mapper = new ObjectMapper();
3.1. 2つの単純なJSONオブジェクトを比較する
JsonNode.equalsメソッドを使用することから始めましょう。 equals()メソッドは完全な(深い)比較を実行します。
s1変数として定義されたJSON文字列があるとします。
{
"employee":
{
"id": "1212",
"fullName": "John Miles",
"age": 34
}
}
そして、それを別のJSON s2と比較したいと思います。
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles"
}
}
入力JSONをJsonNodeとして読み取り、比較してみましょう。
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
入力JSON変数s1とs2の属性の順序は同じではありませんが、equals()メソッドは順序を無視し、それらを等しいものとして扱うことに注意することが重要です。
3.2. Compare Two JSON Objects With a Nested Element
次に、ネストされた要素を持つ2つのJSONオブジェクトを比較する方法を説明します。
s1変数として定義されたJSONから始めましょう。
{
"employee":
{
"id": "1212",
"fullName":"John Miles",
"age": 34,
"contact":
{
"email": "[email protected]",
"phone": "9999999999"
}
}
}
As we can see, the JSON contains a nested element contact.
We want to compare it with another JSON defined by s2:
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles",
"contact":
{
"email": "[email protected]",
"phone": "9999999999"
}
}
}
入力JSONをJsonNodeとして読み取り、比較してみましょう。
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
繰り返しになりますが、 equals()は2つの入力JSONオブジェクトをネストされた要素と比較することもできます。
3.3. リスト要素を含む2つのJSONオブジェクトを比較する
同様に、list要素を含む2つのJSONオブジェクトを比較することもできます。
s1として定義されているこのJSONについて考えてみましょう。
{
"employee":
{
"id": "1212",
"fullName": "John Miles",
"age": 34,
"skills": ["Java", "C++", "Python"]
}
}
We are comparing it with another JSON, s2:
{
"employee":
{
"id": "1212",
"age": 34,
"fullName": "John Miles",
"skills": ["Java", "C++", "Python"]
}
}
入力JSONをJsonNodeとして読み取り、比較してみましょう。
assertEquals(mapper.readTree(s1), mapper.readTree(s2));
2つのリスト要素は、まったく同じ順序で同じ値を持つ場合にのみ、等しいものとして比較されることを知っておくことが重要です。
4. Compare Two JSON Objects With a Custom Comparator
JsonNode.equals works quite well in most cases. Jackson also provides JsonNode.equals(comparator, JsonNode) to configure a custom Java Comparator object.
Let’s understand how to use a custom Comparator.
4.1. 数値を比較するカスタムコンパレータ
Let’s look at how to use a custom Comparator to compare two JSON elements having numeric values.
このJSONを入力s1として使用します。
{
"name": "John",
"score": 5.0
}
s2として定義されている別のJSONと比較してみましょう。
{
"name": "John",
"score": 5
}
私たちはそれを観察する必要があります
入力JSONをJsonNodeとして読み取り、比較してみましょう。
JsonNode actualObj1 = mapper.readTree(s1);
JsonNode actualObj2 = mapper.readTree(s2);
assertNotEquals(actualObj1, actualObj2);
Notice that the two objects are not equal. 標準のequals()メソッドは、値5.0と5を異なるものと見なします。
However, we can use a custom Comparator to compare values 5 and 5.0 and treat them as equal.
最初にコンパレータを作成して、2つのNumericNodeオブジェクトを比較してみましょう。
public class NumericNodeComparator implements Comparator<JsonNode>
{
@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;
}
}
次に、このコンパレータの使用方法を見てみましょう。
NumericNodeComparator cmp = new NumericNodeComparator();
assertTrue(actualObj1.equals(cmp, actualObj2));
4.2. テキスト値を比較するカスタムコンパレータ
2つのJSON値の大文字と小文字を区別しない比較用のカスタムコンパレータの別の例を見てみましょう。
このJSONを入力s1として使用します。
{
"name": "john",
"score": 5
}
s2として定義されている別のJSONと比較してみましょう。
{
"name": "JOHN",
"score": 5
}
As we can see, the attribute name is lowercase in input s1 and uppercase in s2.
最初にコンパレータを作成して、2つのTextNodeオブジェクトを比較してみましょう。
public class TextNodeComparator implements Comparator<JsonNode>
{
@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;
}
}
Let’s see how to compare s1 and s2 using TextNodeComparator:
JsonNode actualObj1 = mapper.readTree(s1);
JsonNode actualObj2 = mapper.readTree(s2);
TextNodeComparator cmp = new TextNodeComparator();
assertNotEquals(actualObj1, actualObj2);
assertTrue(actualObj1.equals(cmp, actualObj2));
最後に、2つのJSONオブジェクトを比較しながらカスタムコンパレータオブジェクトを使用していることがわかりますは、入力JSON要素の値が完全に同じではないが、それらを等しいものとして扱いたい場合に非常に役立ちます。
5. 結論
In this quick article, we’ve seen how to use Jackson to compare two JSON objects and use a custom comparator
As always, the full source code of all the examples discussed here can be found over on GitHub.