Jacksonと2つのJSONオブジェクトを比較する

1. 概要

この記事では、https://www.baeldung.com/jackson [Jackson]-Java用のJSON処理ライブラリを使用して2つのJSONオブジェクトを比較する方法を説明します。

2. Mavenの依存関係

まず、https://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.fasterxml.jackson.core%22%20AND%20a%3A%22jackson-databindを追加しましょう%22 [jackson-databind] Maven依存関係:
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>

3. Jacksonを使用して2つのJSONオブジェクトを比較する

https://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.9.8/com/fasterxml/jackson/databind/ObjectMapper.html[_ObjectMapper_]クラスを使用して、 _https://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.9.8/com/fasterxml/jackson/databind/JsonNode.html [JsonNode。] _としてのオブジェクト
_ObjectMapper_を作成しましょう:
ObjectMapper mapper = new ObjectMapper();

3.1. 2つの単純なJSONオブジェクトを比較する

まずはhttps://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.9.8/com/fasterxml/jackson/databind/JsonNode.html#equals-javaを使用して始めましょう。 lang.Object-[_ 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. 2つのJSONオブジェクトをネストされた要素と比較する

次に、ネストされた要素を持つ2つのJSONオブジェクトを比較する方法について説明します。
_s1_変数として定義されたJSONから始めましょう。
{
    "employee":
    {
        "id": "1212",
        "fullName":"John Miles",
        "age": 34,
        "contact":
        {
            "email": "[email protected]",
            "phone": "9999999999"
        }
    }
}
ご覧のとおり、JSONにはネストされた要素_contact_が含まれています。 _s2_で定義された別のJSONと比較したい:
{
    "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オブジェクトを比較する

同様に、リスト要素を含む2つのJSONオブジェクトを比較することもできます。
_s1_として定義されたこのJSONを考えてみましょう:
{
    "employee":
    {
        "id": "1212",
        "fullName": "John Miles",
        "age": 34,
        "skills": ["Java", "C++", "Python"]
    }
}
別の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. 2つのJSONオブジェクトをカスタムコンパレータと比較する

https://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.9.8/com/fasterxml/jackson/databind/JsonNode.html#equals-java.lang.Object-[_JsonNode.equals_ ]ほとんどの場合、非常にうまく機能します。 Jacksonはhttps://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.9.8/com/fasterxml/jackson/databind/JsonNode.html#equals-java.util.Comparator-comも提供しています.fasterxml.jackson.databind.JsonNode-[_ JsonNode.equals(comparator、JsonNode)_]は、カスタムJava C__omparator__オブジェクトを構成します。 カスタム_Comparator_の使用方法を理解しましょう。

4.1. 数値を比較するカスタムコンパレータ

カスタム__Comparator ___を使用して、数値を持つ2つのJSON要素を比較する方法を理解しましょう。
このJSONを入力_s1_として使用します。
{
    "name": "John",
    "score": 5.0
}
_s2_として定義されている別のJSONと比較してみましょう。
{
    "name": "John",
    "score": 5
}
*入力_s1_と_s2_の属性_score_の値が同じではないことに注意する必要があります。*
入力JSONを_JsonNode_として読み取り、比較してみましょう。
JsonNode actualObj1 = mapper.readTree(s1);
JsonNode actualObj2 = mapper.readTree(s2);

assertNotEquals(actualObj1, actualObj2);
気付くように、2つのオブジェクトは等しくありません。 標準の_equals()_メソッドは、値5.0と5を異なるものと見なします。
ただし、*カスタム_Comparator_を使用して、値5と5.0を比較し、それらを等しいものとして扱うことができます*。
最初に_Comparator_を作成して、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;
    }
}
次に、この_Comparator_の使用方法を見てみましょう。
NumericNodeComparator cmp = new NumericNodeComparator();
assertTrue(actualObj1.equals(cmp, actualObj2));

4.2. テキスト値を比較するカスタムコンパレータ

2つのJSON値の大文字と小文字を区別しない比較のための別の*カスタム_Comparator_の例を見てみましょう。
このJSONを入力_s1_として使用します。
{
    "name": "john",
    "score": 5
}
_s2_として定義されている別のJSONと比較してみましょう。
{
    "name": "JOHN",
    "score": 5
}
ご覧のとおり、属性_name_は入力_s1_では小文字で、_s2_では大文字です。
最初に_Comparator_を作成して、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;
    }
}
_TextNodeComparatorを使用して_s1_と_s2_を比較する方法を見てみましょう:_
JsonNode actualObj1 = mapper.readTree(s1);
JsonNode actualObj2 = mapper.readTree(s2);

TextNodeComparator cmp = new TextNodeComparator();

assertNotEquals(actualObj1, actualObj2);
assertTrue(actualObj1.equals(cmp, actualObj2));
最後に、2つのJSONオブジェクトを比較しながらカスタムコンパレータオブジェクトを使用することを確認できます

5. 結論

このクイックチュートリアルでは、Jacksonを使用して2つのJSONオブジェクトを比較し、カスタムコンパレーター__を使用する方法を見てきました。 __
もちろん、いつものように、ここで説明したすべての例の完全なソースコードは、https://github.com/eugenp/tutorials/tree/master/jackson-2 [GitHubで]にあります。