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

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

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

前回に引き続き,Gsonのユーザーガイドを見ていきます。

配列

Gsonのユーザーガイドには,intとStringの配列の例がありました。

Person.java

package com.rmstar.gson.userguide;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return String.format("%s %d才", name, age);
    }
}

自分で定義したPersonクラスの配列も試してみました。



package com.rmstar.gson.userguide;

import com.google.gson.Gson;

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

        int[] ints = new int[] {
                1, 2, 3, 4, 5
        };
        String[] strings = new String[] {
                "abc", "def", "ghi"
        };
        Person[] persons = new Person[] {
                new Person("taro", 20),
                new Person("jiro", 17),
                new Person("saburo", 14),
        };

        System.out.println(gson.toJson(ints));
        System.out.println(gson.toJson(strings));
        System.out.println(gson.toJson(persons));

        String intsString = "[3,2,1,0]";
        String stringsString = "[\"AAA\",\"BBB\",\"CCC\"]";
        String personString = "[{\"name\":\"Alice\",\"age\":24},{\"name\":\"Bob\",\"age\":25}]";

        int[] deserializedInts = 
                gson.fromJson(intsString, int[].class);
        String[] deserializedStrings =
                gson.fromJson(stringsString, String[].class);
        Person[] deserializedPersons =
                gson.fromJson(personString, Person[].class);

        System.out.println("=== Deserialized Ints ===");
        for (int value : deserializedInts) {
            System.out.println(value);
        }

        System.out.println("=== Deserialized Strings ===");
        for (String value : deserializedStrings) {
            System.out.println(value);
        }

        System.out.println("=== Deserialized Persons ===");
        for (Person value : deserializedPersons) {
            System.out.println(value);
        }

    }
}


実行結果は,


[1,2,3,4,5]
["abc","def","ghi"]
[{"name":"taro","age":20},{"name":"jiro","age":17},{"name":"saburo","age":14}]
=== Deserialized Ints ===
3
2
1
0
=== Deserialized Strings ===
AAA
BBB
CCC
=== Deserialized Persons ===
Alice 24才
Bob 25才


となりました。



ついでに,多次元配列もやってみました。

package com.rmstar.gson.userguide;

import com.google.gson.Gson;

public class MultiArrayEamaple {
    public static void main(String[] args) {
        System.out.println("===Multidimensional Array===");
        int[][] multiArray = new int[][] {
                new int[3],
                new int[3],
                new int[3],
        };
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                multiArray[i][j] = i + 2 * j;
            }
        }
        for (int[] a : multiArray) {
            System.out.println(String.format("%d %d %d", a[0], a[1], a[2]));
        }

        System.out.println("===Serialize===");
        Gson gson = new Gson();
        String serialized = gson.toJson(multiArray);
        System.out.println(gson.toJson(multiArray));

        System.out.println("===Deserialize===");
        int[][] deserialzed = gson.fromJson(serialized, int[][].class);
        for (int[] a : deserialzed) {
            System.out.println(String.format("%d %d %d", a[0], a[1], a[2]));
        }
    }
}

実行結果は次の通りです。

===Multidimensional Array===
0 2 4
1 3 5
2 4 6
===Serialize===
[[0,2,4],[1,3,5],[2,4,6]]
===Deserialize===
0 2 4
1 3 5
2 4 6


多次元配列も可能なようですね。



コレクション

package com.rmstar.gson.userguide;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

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

        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);

        System.out.println("=== Serialize ===");
        System.out.println(gson.toJson(list));

        System.out.println("=== Deserialize ===");
        String jsonString = "[0,10,100]";
        Type listType = new TypeToken<List<Integer>>() {
        }.getType();

        List<Integer> deserialized = 
                gson.fromJson(jsonString, listType);
        System.out.println(deserialized);
        System.out.println(deserialized.getClass().getName());
    }
}


実行結果は,

=== Serialize ===
[1,2,3]
=== Deserialize ===
[0, 10, 100]
java.util.ArrayList

となりました。

SetやMapでもやってみようと思います。

package com.rmstar.gson.userguide;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

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

        Set<Integer> set = new TreeSet<Integer>();
        set.add(1);
        set.add(2);
        set.add(3);

        Map<String, Integer> map = new TreeMap<String, Integer>();
        map.put("a", 1);
        map.put("b", 2);

        System.out.println("=== Serialize ===");
        System.out.println(gson.toJson(set));
        System.out.println(gson.toJson(map));

        System.out.println("=== Deserialize ===");
        String setString = "[0,10,100]";
        String mapString = "{\"X\":10,\"Y\":-10}";
        Type setType = new TypeToken<Set<Integer>>() {
        }.getType();
        Type mapType = new TypeToken<Map<String, Integer>>() {
        }.getType();

        Set<Integer> deserializedSet =
                gson.fromJson(setString, setType);
        System.out.println(deserializedSet);
        System.out.println(deserializedSet.getClass().getName());

        Map<String, Integer> deserializedMap =
                gson.fromJson(mapString, mapType);
        System.out.println(deserializedMap);
        System.out.println(deserializedMap.getClass().getName());
    }
}


実行結果は,

=== Serialize ===
[1,2,3]
{"a":1,"b":2}
=== Deserialize ===
[0, 10, 100]
java.util.LinkedHashSet
{X=10, Y=-10}
java.util.LinkedHashMap


でした。

Type mapType = new TypeToken<Map<String, Integer>>() {
}.getType();

のように,TypeToken型のインスタンスを作る際の型引数に

  • Listインターフェース型
  • Setインターフェース型
  • Mapインターフェース型

を指定した場合,それぞれ

が生成されました。


当然インターフェースでなく,
インスタンス化したいクラスを指定してのインスタンス化も出来るようです。

package com.rmstar.gson.userguide;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.TreeMap;

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

        String listString = "[1,2,1]";
        String setString = "[0,10,100]";
        String mapString = "{\"X\":10,\"Y\":-10}";

        Type listType = new TypeToken<LinkedList<Integer>>() {
        }.getType();
        Type setType = new TypeToken<HashSet<Integer>>() {
        }.getType();
        Type mapType = new TypeToken<TreeMap<String, Integer>>() {
        }.getType();

        Class<?> listClass =
                gson.fromJson(listString, listType).getClass();
        Class<?> setClass =
                gson.fromJson(setString, setType).getClass();
        Class<?> mapClass =
                gson.fromJson(mapString, mapType).getClass();

        System.out.println(listClass.getName());
        System.out.println(setClass.getName());
        System.out.println(mapClass.getName());
    }
}

実行結果は,

java.util.LinkedList
java.util.HashSet
java.util.TreeMap

です。





総称型のシリアライズとデシリアライズ

toJson(obj)メソッドを呼んだ時,
内部的にobj.getClass()メソッドを呼んでいるそうです。
シリアライズするフィールドの情報を得るためだそうです。
同じように,fromJsonメソッドの第二引数にもclass型を入れますよね。

非総称型のオブジェクトをデシリアライズする場合は
int.classのようなクラス型でうまくいくのですが,
総称型のオブジェクトの場合うまくいきません。
総称型の情報が無くなっているからというのが原因みたいです。

Fuga.java

package com.rmstar.gson.userguide;

public class Fuga {
    int fuga;

    @Override
    public String toString() {
        return String.valueOf(fuga);
    }
}

Hoge.java

package com.rmstar.gson.userguide;

public class Hoge<T> {
    T hoge;

    @Override
    public String toString() {
        return String.format("Hoge : %s", hoge.toString());
    }
}

GenericTypeExample.java

package com.rmstar.gson.userguide;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;

public class GenericTypeExample {
    public static void main(String[] args) {

        System.out.println("=== Define ===");
        Gson gson = new Gson();

        Hoge<Fuga> a = new Hoge<Fuga>();
        a.hoge = new Fuga();
        a.hoge.fuga = 1;
        System.out.println(a);

        System.out.println("=== Serealize ===");
        String jsonA = gson.toJson(a);
        System.out.println(jsonA);

        System.out.println("=== Deserealize ===");
        Hoge<Fuga> deserializedA;

        deserializedA = gson.fromJson(jsonA, Hoge.class);
        System.out.println(deserializedA);

        Type type = new TypeToken<Hoge<Fuga>>() {
        }.getType();
        deserializedA = gson.fromJson(jsonA, type);
        System.out.println(deserializedA);
    }
}


GenericTypeExample.javaの実行結果は,

=== Define ===
Hoge : 1
=== Serealize ===
{"hoge":{"fuga":1}}
=== Deserealize ===
Hoge : {fuga=1.0}
Hoge : 1

でした。

Hoge.classをfomJsonの引数に取った場合には,
正しくデシリアライズできていないみたいです。




今回はこの辺で。

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