いろいろガンガンいこうぜ。体も大事に

普段はJavaでAndroidアプリ開発しているプログラマーのブログです。

Gsonのユーザーガイドを見てみた (1)

Gson User Guideに載っているサンプルを実際にやってみたり,書いてあるポイントを自分なりにまとめてみました。



基本型

package com.rmstar.gson.userguide;

import com.google.gson.Gson;

public class Primitives {
    public static void main(String[] args) {
        serialize();
        System.out.println();
        deserialize();
    }

    public static void serialize() {
        Gson gson = new Gson();

        System.out.println("===Serialize===");
        System.out.println(gson.toJson(1));
        System.out.println(gson.toJson("abcd"));
        System.out.println(gson.toJson(new Long(10)));
        int[] values = {
                1
        };
        System.out.println(gson.toJson(values));
    }

    public static void deserialize() {
        Gson gson = new Gson();

        int oneInt = gson.fromJson("1", int.class);
        Integer oneInteger = gson.fromJson("1", Integer.class);
        Boolean falseBoolean = gson.fromJson("false", Boolean.class);
        String str = gson.fromJson("\"abc\"", String.class);
        String[] anotherStr = gson.fromJson("[\"abc\"]", String[].class);

        System.out.println("===Deserialize===");
        System.out.println(oneInt);
        System.out.println(oneInteger);
        System.out.println(falseBoolean);
        System.out.println(str);
        System.out.println(anotherStr[0]);
        System.out.println(String.format("length : %d", anotherStr.length));
    }
}


実行結果は,


===Serialize===
1
"abcd"
10
[1]

===Deserialize===
1
1
false
abc
abc
length : 1

となりました。





オブジェクトの例

package com.rmstar.gson.userguide;

import com.google.gson.Gson;

public class ObjectExamples {
    private static class SampleObject {
        private int value1 = 1;
        private String value2 = "abc";
        private transient int value3 = 3;

        public SampleObject() {
        }
    }

    public static void main(String[] args) {
        SampleObject sampleObject = new SampleObject();
        Gson gson = new Gson();
        String jsonString = gson.toJson(sampleObject);
        System.out.println(jsonString);

        SampleObject deserialized = gson.fromJson(jsonString, SampleObject.class);
    }
}

実行結果は,

{"value1":1,"value2":"abc"}


でした。

ポイントは

  • フィールドに基本型を使った場合は問題なし。
  • JSON形式への変換,JSON形式からの変換。どちらもフィールドにアノテーションをつける必要なし。そのクラスと親クラスの全てのフィールドが変換に含まれる。
  • transient修飾子がついた場合,JSON形式への変換,JSON形式からの変換どちらも無視される。
  • nullを正しく扱うことが出来る。
    • JSON形式の文字列への変換(シリアライゼーション)では,値がnullのフィールドは変換結果のJSON文字列中に含まれない。
    • JSON形式の文字列からの変換(デシリアライゼーション)では,文字列中に含まれていない要素に対応するフィールドはnullとなる。
  • フィールドがsynethticならば,シリアライゼーションでも,デシリアライゼーションでも無視される。
  • インナークラス中のアウタークラス,無名クラス,ローカルクラスに該当するフィールドは無視されて,シリアライゼーションにもデシリアライゼーションにも含まれない。


だそうです。




いろいろ試してみました。

package com.rmstar.gson.userguide;

import com.google.gson.Gson;

public class Ex1 {

    private static class A {
        private int a;

        A(int a) {
            this.a = a;
        }
    }

    private static class B extends A {
        private int b;

        B(int a, int b) {
            super(a);
            this.b = b;
        }
    }

    private static class C extends B {
        private int c;

        C(int a, int b, int c) {
            super(a, b);
            this.c = c;
        }
    }

    public static void main(String[] args) {
        C c = new C(1, 2, 3);
        Gson gson = new Gson();
        System.out.println(gson.toJson(c));
    }
}


実行結果は,

{"c":3,"b":2,"a":1}


親クラスのプライベートなフィールドもJSON形式に変換されるらしいです。



次にnullの取り扱い。

package com.rmstar.gson.userguide;

import com.google.gson.Gson;

public class Ex2 {

    private static class Sample {
        private String name;
        private String value;

        Sample(String name, String value) {
            this.name = name;
            this.value = value;
        }
    }

    public static void main(String[] args) {
        Gson gson = new Gson();

        Sample sampleA = new Sample("a", "v1");
        Sample sampleB = new Sample("b", null);

        System.out.println(gson.toJson(sampleA));
        System.out.println(gson.toJson(sampleB));

        String sampleCJsonString = "{\"name\":\"c\"}";
        Sample sampleC = gson.fromJson(sampleCJsonString, Sample.class);
        System.out.println(sampleC.name);
        System.out.println(sampleC.value);
    }
}

実行結果は,

{"name":"a","value":"v1"}
{"name":"b"}
c
null

となるようです。




ネストされたクラス(インナークラスを含む)

Gsonはとても簡単にstaticなネストされたクラスをシリアライズできるようです。
また,Gsonはstaticなネストされたクラスをデシリアライズすることも可能です。


しかし,Gsonは純粋なインナークラスは自動的にデシリアライズできません。
インナークラスの引数なしのコンストラクターは,そのインナークラスを保持しているオブジェクトの参照が必要で,それがデシリアライズの時に利用不可能だからだそうです。


インナークラスをstaticにするか,カスタマイズされたInstanceCreatorを作る必要があるようです。


InstanceCreatorを使ってみました。
A.java

package com.rmstar.gson.userguide;

public class A {
    public String a;

    class B {

        public String b;

        public B() {
            // No args constructor for B
        }
    }
}


InstanceCreatorForB.java

package com.rmstar.gson.userguide;

import com.google.gson.InstanceCreator;

import java.lang.reflect.Type;

public class InstanceCreatorForB implements InstanceCreator<A.B> {
    private final A a;

    public InstanceCreatorForB(A a) {
        this.a = a;
    }

    public A.B createInstance(Type type) {
        return a.new B();
    }
}


Ex3.java

package com.rmstar.gson.userguide;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Ex3 {

    public static void main(String[] args) {
        A instanceA = new A();

        InstanceCreatorForB creator =
                new InstanceCreatorForB(instanceA);

        Gson gson = new GsonBuilder()
                .registerTypeAdapter(A.B.class, creator)
                .create();

        A.B instanceB = gson.fromJson("{\"b\":\"abc\"}", A.B.class);
        System.out.println(instanceB.b);
    }
}


ちょっと面倒ですね。





今回はこの変で。


それでは,また会えることを祈りつつ。