Gsonデシリアライゼーションクックブック

Gson Deserialization Cookbook

このクックブックでは、人気のあるGson libraryを使用して、unmarshall JSON into Java objectsへのさまざまな方法を探っています。

1. JSONを単一の基本オブジェクトに逆シリアル化します

簡単に始めましょう–unmarshall a simple json to a Java object – Fooに行きます:

public class Foo {
    public int intValue;
    public String stringValue;

    // + standard equals and hashCode implementations
}

そして解決策:

@Test
public void whenDeserializingToSimpleObject_thenCorrect() {
    String json = "{"intValue":1,"stringValue":"one"}";

    Foo targetObject = new Gson().fromJson(json, Foo.class);

    assertEquals(targetObject.intValue, 1);
    assertEquals(targetObject.stringValue, "one");
}

参考文献:

Gsonのシリアル化からフィールドを除外する

Gsonでシリアル化からフィールドを除外するために利用可能なオプションを調べます。

Gson Serialization Cookbook

Gsonライブラリを使用してエンティティをシリアル化する方法を学びます。

ジャクソンvs Gson

ジャクソンとGsonによるシリアル化の迅速かつ実用的なガイド。

2. JSONをジェネリックオブジェクトに逆シリアル化する

次へ–ジェネリックを使用してオブジェクトを定義しましょう:

public class GenericFoo {
    public T theValue;
}

そして、いくつかのjsonをこのタイプのオブジェクトにアンマーシャルします。

@Test
public void whenDeserializingToGenericObject_thenCorrect() {
    Type typeToken = new TypeToken>() { }.getType();
    String json = "{"theValue":1}";

    GenericFoo targetObject = new Gson().fromJson(json, typeToken);

    assertEquals(targetObject.theValue, new Integer(1));
}

3. 余分な未知のフィールドを持つJSONをオブジェクトに逆シリアル化します

次へ–追加のunknown fieldsを含む複雑なjsonを逆シリアル化します。

@Test
public void givenJsonHasExtraValues_whenDeserializing_thenCorrect() {
    String json =
      "{"intValue":1,"stringValue":"one","extraString":"two","extraFloat":2.2}";
    Foo targetObject = new Gson().fromJson(json, Foo.class);

    assertEquals(targetObject.intValue, 1);
    assertEquals(targetObject.stringValue, "one");
}

ご覧のとおり、Gson will ignore the unknown fieldsは、可能なフィールドと単純に一致します。

4. フィールド名が一致しないJSONをオブジェクトに逆シリアル化する

次に、Fooオブジェクトのフィールドと単純に一致しないフィールドを含むjson文字列をGsonがどのように処理するかを見てみましょう。

@Test
public void givenJsonHasNonMatchingFields_whenDeserializingWithCustomDeserializer_thenCorrect() {
    String json = "{"valueInt":7,"valueString":"seven"}";

    GsonBuilder gsonBldr = new GsonBuilder();
    gsonBldr.registerTypeAdapter(Foo.class, new FooDeserializerFromJsonWithDifferentFields());
    Foo targetObject = gsonBldr.create().fromJson(json, Foo.class);

    assertEquals(targetObject.intValue, 7);
    assertEquals(targetObject.stringValue, "seven");
}

a custom deserializerを登録したことに注意してください。これにより、json文字列からフィールドを正しく解析し、Fooにマップできました。

public class FooDeserializerFromJsonWithDifferentFields implements JsonDeserializer {

    @Override
    public Foo deserialize
      (JsonElement jElement, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {
        JsonObject jObject = jElement.getAsJsonObject();
        int intValue = jObject.get("valueInt").getAsInt();
        String stringValue = jObject.get("valueString").getAsString();
        return new Foo(intValue, stringValue);
    }
}

5. JSON配列をオブジェクトのJava配列に逆シリアル化します

次に、Fooオブジェクトのa json array into a Java arrayを逆シリアル化します。

@Test
public void givenJsonArrayOfFoos_whenDeserializingToArray_thenCorrect() {
    String json = "[{"intValue":1,"stringValue":"one"}," +
      "{"intValue":2,"stringValue":"two"}]";
    Foo[] targetArray = new GsonBuilder().create().fromJson(json, Foo[].class);

    assertThat(Lists.newArrayList(targetArray), hasItem(new Foo(1, "one")));
    assertThat(Lists.newArrayList(targetArray), hasItem(new Foo(2, "two")));
    assertThat(Lists.newArrayList(targetArray), not(hasItem(new Foo(1, "two"))));
}

6. JSON配列をJavaコレクションに逆シリアル化します

次に、json配列directly into a Java Collection

@Test
public void givenJsonArrayOfFoos_whenDeserializingCollection_thenCorrect() {
    String json =
      "[{"intValue":1,"stringValue":"one"},{"intValue":2,"stringValue":"two"}]";
    Type targetClassType = new TypeToken>() { }.getType();

    Collection targetCollection = new Gson().fromJson(json, targetClassType);
    assertThat(targetCollection, instanceOf(ArrayList.class));
}

7. JSONをネストされたオブジェクトに逆シリアル化する

次に、ネストされたオブジェクト–FooWithInnerを定義しましょう:

public class FooWithInner {
    public int intValue;
    public String stringValue;
    public InnerFoo innerFoo;

    public class InnerFoo {
        public String name;
    }
}

そして、このネストされたオブジェクトを含む入力をデシリアライズする方法は次のとおりです。

@Test
public void whenDeserializingToNestedObjects_thenCorrect() {
    String json = "{\"intValue\":1,\"stringValue\":\"one\",\"innerFoo\":{\"name\":\"inner\"}}";

    FooWithInner targetObject = new Gson().fromJson(json, FooWithInner.class);

    assertEquals(targetObject.intValue, 1);
    assertEquals(targetObject.stringValue, "one");
    assertEquals(targetObject.innerFoo.name, "inner");
}

8. カスタムコンストラクターを使用してJSONを逆シリアル化する

最後に、デシリアライズ中に、デフォルトの代わりに特定のコンストラクター(引数なしのコンストラクター)をInstanceCreatorを使用して強制的に使用する方法を見てみましょう。

public class FooInstanceCreator implements InstanceCreator {

    @Override
    public Foo createInstance(Type type) {
        return new Foo("sample");
    }
}

そして、これが逆シリアル化でFooInstanceCreatorを使用する方法です:

@Test
public void whenDeserializingUsingInstanceCreator_thenCorrect() {
    String json = "{\"intValue\":1}";

    GsonBuilder gsonBldr = new GsonBuilder();
    gsonBldr.registerTypeAdapter(Foo.class, new FooInstanceCreator());
    Foo targetObject = gsonBldr.create().fromJson(json, Foo.class);

    assertEquals(targetObject.intValue, 1);
    assertEquals(targetObject.stringValue, "sample");
}

次のコンストラクターを使用したため、nullの代わりにFoo.stringValuesampleに等しいことに注意してください。

public Foo(String stringValue) {
    this.stringValue = stringValue;
}

9. 結論

この記事では、Gsonライブラリをparse JSON inputに活用する方法を示します。これは、単一オブジェクトと複数オブジェクトの両方の最も一般的なユースケースについて説明しています。

これらすべての例とコードスニペットcan be found in my github projectの実装–これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。