1. 概要

このチュートリアルでは、 Gsonを使用してプリミティブ値をシリアル化および逆シリアル化する方法を学びます。 Googleは、JSONをシリアル化および逆シリアル化するためのGsonライブラリを開発しました。 さらに、プリミティブの処理に関して、Gsonライブラリが持ついくつかの特定の癖について学習します。

一方、配列、コレクション、ネストされたオブジェクト、またはその他のカスタマイズを操作する必要がある場合は、Gsonを使用したシリアル化とGsonを使用した逆シリアル化に関する追加のチュートリアルがあります。

2. Mavenの依存関係

Gsonを使用するには、pomにGson依存関係を追加する必要があります。

<dependency> 
    <groupId>com.google.code.gson</groupId> 
    <artifactId>gson</artifactId> 
    <version>2.8.5</version> 
</dependency>

3. プリミティブ型のシリアル化

Gsonを使用したシリアル化は非常に簡単です。 例として次のモデルを使用します。

public class PrimitiveBundle {
    public byte byteValue;
    public short shortValue;
    public int intValue;
    public long longValue;
    public float floatValue;
    public double doubleValue;
    public boolean booleanValue;
    public char charValue;
}

まず、いくつかのテスト値を使用してインスタンスを初期化します。

PrimitiveBundle primitiveBundle = new PrimitiveBundle();
primitiveBundle.byteValue = (byte) 0x00001111;
primitiveBundle.shortValue = (short) 3;
primitiveBundle.intValue = 3;
primitiveBundle.longValue = 3;
primitiveBundle.floatValue = 3.5f;
primitiveBundle.doubleValue = 3.5;
primitiveBundle.booleanValue = true;
primitiveBundle.charValue = 'a';

次に、それをシリアル化できます。

Gson gson = new Gson();
String json = gson.toJson(primitiveBundle);

最後に、シリアル化された結果を確認できます。

{  
   "byteValue":17,
   "shortValue":3,
   "intValue":3,
   "longValue":3,
   "floatValue":3.5,
   "doubleValue":3.5,
   "booleanValue":true,
   "charValue":"a"
}

この例からいくつかの詳細に注意する必要があります。 手始めに、バイト値はモデルのようにビットの文字列としてシリアル化されません。 それに加えて、short、int、longの区別はありません。 また、floatとdoubleの区別はありません。

もう1つの注意点は、文字列が文字値を表すことです。

実際、これらの最後の3つのことはGsonとは何の関係もありませんが、それがJSONの定義方法です。

3.1. 特別な浮動小数点値のシリアル化

Javaには、無限大を表す定数Float.POSITIVE_INFINITYおよびNEGATIVE_INFINITYがあります。 Gsonは、これらの特別な値をシリアル化できません。

public class InfinityValuesExample {
    public float negativeInfinity;
    public float positiveInfinity;
}
InfinityValuesExample model = new InfinityValuesExample();
model.negativeInfinity = Float.NEGATIVE_INFINITY;
model.positiveInfinity = Float.POSITIVE_INFINITY;

Gson gson = new Gson();
gson.toJson(model);

そうしようとすると、IllegalArgumentExceptionが発生します。

NaN をシリアル化しようとすると、 IllegalArgumentException も発生します。これは、この値がJSON仕様で許可されていないためです。

同じ理由で、Double。POSITIVE_INFINITY、NEGATIVE_INFINITY、または NaN をシリアル化しようとすると、IllegalArgumentException。もスローされます。

4. プリミティブタイプの逆シリアル化

前の例で取得したJSON文字列を逆シリアル化する方法を見てみましょう。

逆シリアル化は、シリアル化と同じくらい簡単です。

Gson gson = new Gson();
PrimitiveBundle model = gson.fromJson(json, PrimitiveBundle.class);

最後に、モデルに目的の値が含まれていることを確認できます。

assertEquals(17, model.byteValue);
assertEquals(3, model.shortValue);
assertEquals(3, model.intValue);
assertEquals(3, model.longValue);
assertEquals(3.5, model.floatValue, 0.0001);
assertEquals(3.5, model.doubleValue, 0.0001);
assertTrue(model.booleanValue);
assertEquals('a', model.charValue);

4.1. 文字列値の逆シリアル化

有効な値が文字列内に配置されると、Gsonはそれを解析し、期待どおりに処理します。

String json = "{\"byteValue\": \"15\", \"shortValue\": \"15\", "
  + "\"intValue\": \"15\", \"longValue\": \"15\", \"floatValue\": \"15.0\""
  + ", \"doubleValue\": \"15.0\"}";

Gson gson = new Gson();
PrimitiveBundleInitialized model = gson.fromJson(json, PrimitiveBundleInitialized.class);
assertEquals(15, model.byteValue);
assertEquals(15, model.shortValue);
assertEquals(15, model.intValue);
assertEquals(15, model.longValue);
assertEquals(15, model.floatValue, 0.0001);
assertEquals(15, model.doubleValue, 0.0001);

文字列値をブール型に逆シリアル化できないことに注意してください。

4.2. デシリアライズ 空の文字列値

一方、空の文字列を使用して次のJSONを逆シリアル化してみましょう。

String json = "{\"byteValue\": \"\", \"shortValue\": \"\", "
  + "\"intValue\": \"\", \"longValue\": \"\", \"floatValue\": \"\""
  + ", \"doubleValue\": \"\"}";

Gson gson = new Gson();
gson.fromJson(json, PrimitiveBundleInitialized.class);

これにより、 JsonSyntaxException が発生します。これは、プリミティブを逆シリアル化するときに空の文字列が予期されないためです。

4.3. ヌル値の逆シリアル化

値がnullのフィールドを逆シリアル化しようとすると、Gsonはそのフィールドを無視します。 たとえば、次のクラスの場合:

public class PrimitiveBundleInitialized {
    public byte byteValue = (byte) 1;
    public short shortValue = (short) 1;
    public int intValue = 1;
    public long longValue = 1L;
    public float floatValue = 1.0f;
    public double doubleValue = 1;
}

Gsonはnullフィールドを無視します。

String json = "{\"byteValue\": null, \"shortValue\": null, "
  + "\"intValue\": null, \"longValue\": null, \"floatValue\": null"
  + ", \"doubleValue\": null}";

Gson gson = new Gson();
PrimitiveBundleInitialized model = gson.fromJson(json, PrimitiveBundleInitialized.class);

assertEquals(1, model.byteValue);
assertEquals(1, model.shortValue);
assertEquals(1, model.intValue);
assertEquals(1, model.longValue);
assertEquals(1, model.floatValue, 0.0001);
assertEquals(1, model.doubleValue, 0.0001);

4.4. オーバーフローする値の逆シリアル化

これは、Gsonが予期せず処理する非常に興味深いケースです。 デシリアライズしようとしています:

{"value": 300}

モデルの場合:

class ByteExample {
    public byte value;
}

その結果、オブジェクトの値は44になります。 これらの場合、代わりに例外が発生する可能性があるため、処理が不十分です。これにより、アプリケーションを介して伝播する検出できないミスを防ぐことができます。

4.5. 浮動小数点数の逆シリアル化

次に、次のJSONをByteExampleオブジェクトに逆シリアル化してみましょう。

{"value": 2.3}

ここでGsonは正しいことを行い、サブタイプがNumberFormatExceptionであるJsonSyntaxExceptionを発生させます。 どのディスクリートタイプ( byte short int long )を使用しても、同じ結果が得られます。

値が「.0」で終わる場合、Gsonは期待どおりに番号を逆シリアル化します。

4.6. 数値ブール値の逆シリアル化

ブール値は、「true」または「false」ではなく、0または1としてコード化される場合があります。 Gsonはデフォルトでこれを許可していません。 たとえば、逆シリアル化しようとすると、次のようになります。

{"value": 1}

モデルに:

class BooleanExample {
    public boolean value;
}

Gsonは、IllegalStateExceptionの例外サブタイプでJsonSyntaxExceptionを発生させます。 これは、数値が一致しなかった場合に発生するNumberFormatExceptionとは対照的です。 これを変更したい場合は、カスタムデシリアライザーを使用できます。

4.7. Unicode文字の逆シリアル化

Unicode文字の逆シリアル化には追加の構成は必要ないことに注意してください。

たとえば、JSON:

{"value": "\u00AE"}

®文字になります。

5. 結論

これまで見てきたように、GsonはJSONおよびJavaプリミティブ型を操作する簡単な方法を提供します。 単純なプリミティブ型を処理する場合でも、注意すべき予期しない動作がいくつかあります。

この記事の完全な実装は、 GitHubプロジェクトにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。