Gsonのユーザーガイドを見てみた (3)
前回,前々回に引き続き,Gsonのユーザーガイドを見ていきます。
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); } }
サンプルとして,このクラスを使います。
JSONの表示フォーマット.単純な形式と分かりやすい形式
package com.rmstar.gson.userguide; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.util.ArrayList; import java.util.List; public class PrettyPrinting { public static void main(String[] args) { Gson gson; Person person = new Person("Alice", 25); List<Person> personList = new ArrayList<Person>(); personList.add(new Person("Taro", 20)); personList.add(new Person("Jiro", 17)); personList.add(new Person("Saburo", 14)); System.out.println("===Compact==="); gson = new Gson(); System.out.println(gson.toJson(person)); System.out.println(gson.toJson(personList)); System.out.println(); System.out.println("===Pretty Printing==="); gson = new GsonBuilder().setPrettyPrinting().create(); System.out.println(gson.toJson(person)); System.out.println(gson.toJson(personList)); } }
実行結果は,
===Compact=== {"name":"Alice","age":25} [{"name":"Taro","age":20},{"name":"Jiro","age":17},{"name":"Saburo","age":14}] ===Pretty Printing=== { "name": "Alice", "age": 25 } [ { "name": "Taro", "age": 20 }, { "name": "Jiro", "age": 17 }, { "name": "Saburo", "age": 14 } ]
となります。
new Gson().toJson(object)
として生成したGsonでの出力文字列は,空白も改行もありません。
new GsonBuilder().setPrettyPrinting().create().toJson(object)
一方で,GsonBuilderを用いてGsonクラスのインスタンスを生成し,
setPrettyPrinting()を行った後にGson型のインスタンスを生成すれば,
上記のように空白が挿入されたり改行付きで表示されたりします。
nullオブジェクトのサポート
package com.rmstar.gson.userguide; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class NullObjectSupport { public static void main(String[] args) { Person person = new Person(null, 20); Gson gson; gson = new Gson(); System.out.println(gson.toJson(person)); gson = new GsonBuilder().serializeNulls().create(); System.out.println(gson.toJson(person)); } }
実行結果
{"age":20} {"name":null,"age":20}
普通にGsonを用いた場合はnullのフィールドは無視されます。
nullを出力したい場合は,
Gsonクラスをインスタンス化する際,
new GsonBuilder().serializeNulls().create()
とすれば,nullは無視されなくなります。
バージョニング
package com.rmstar.gson.userguide; import com.google.gson.annotations.Since; public class VersionedObject { private final String v1; @Since(2) private final String v2; @Since(3) private final String v3; public VersionedObject() { v1 = "version1"; v2 = "version2"; v3 = "version3"; } }
各フィールドに@Sinceアノテーションを上記のように記述して,
package com.rmstar.gson.userguide; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class VersioningSupport { public static void main(String[] args) { Gson gson; VersionedObject object = new VersionedObject(); gson = new Gson(); System.out.println(gson.toJson(object)); gson = new GsonBuilder().setVersion(1).create(); System.out.println(gson.toJson(object)); gson = new GsonBuilder().setVersion(2).create(); System.out.println(gson.toJson(object)); gson = new GsonBuilder().setVersion(3).create(); System.out.println(gson.toJson(object)); } }
上記のように,gsonをインスタンス化すれば,
{"v1":"version1","v2":"version2","v3":"version3"} {"v1":"version1"} {"v1":"version1","v2":"version2"} {"v1":"version1","v2":"version2","v3":"version3"}
実行結果はこのようになります。
@Sinceアノテーションを用いれば,
同じオブジェクト・コードでバージョンによる差異を上手に扱えるみたいです。
もしGsonのインスタンスにバージョンの設定がされていないのであれば,
バージョンに関わらず全てのフィールドがシリアライズ・デシリアライズされるようです。
@Sinceアノテーションはクラスに設定することもできるようです。
package com.rmstar.gson.userguide; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.Since; import java.util.ArrayList; import java.util.List; public class VersioningSupport { private static class V1 { final String v = "version1"; } @Since(2) private static class V2 { final String v = "version2"; } @Since(3) private static class V3 { final String v = "version3"; } public static void main(String[] args) { Gson gson; List<Object> list = new ArrayList<Object>(); list.add(new V1()); list.add(new V2()); list.add(new V3()); System.out.println("===Version1==="); gson = new GsonBuilder().setVersion(1).create(); System.out.println(gson.toJson(list)); System.out.println("===Version2==="); gson = new GsonBuilder().setVersion(2).create(); System.out.println(gson.toJson(list)); System.out.println("===Version3==="); gson = new GsonBuilder().setVersion(3).create(); System.out.println(gson.toJson(list)); } }
実行結果は,
===Version1=== [{"v":"version1"},null,null] ===Version2=== [{"v":"version1"},{"v":"version2"},null] ===Version3=== [{"v":"version1"},{"v":"version2"},{"v":"version3"}]
となりました。
フィールドのネーミング
package com.rmstar.gson.userguide; public class Animal { private final String mName; private final int mWeight; public Animal(String name, int weight) { mName = name; mWeight = weight; } }
このようなクラスがあったとして,
package com.rmstar.gson.userguide; import com.google.gson.Gson; public class JSONFieldNamingSupport { public static void main(String[] args) { Animal pochi = new Animal("Pochi", 35); System.out.println(new Gson().toJson(pochi)); } }
この様にGsonを使うと,
{"mName":"Pochi","mWeight":35}
こうなります。
命名規約などでフィールドにmをつけなくてはいけない場合,
Gsonでの出力にもmがついてしまいます。
Animalクラスを次の用に書き換えます。
package com.rmstar.gson.userguide; import com.google.gson.annotations.SerializedName; public class Animal { @SerializedName("name") private final String mName; @SerializedName("weight") private final int mWeight; public Animal(String name, int weight) { mName = name; mWeight = weight; } }
実行結果は以下のようになりました。
{"name":"Pochi","weight":35}
クラスのフィールド名は元のままですが,GsonでのJSON形式の文字列はmを取ることが出来ました。
シリアライズ・デシリアライズでのフィールドの除外
Gsonではシリアライズ・デシリアライズにおいて,
クラス・フィールド・ある型のフィールドを除外するための多くの仕組みが準備されています。
まずは,修飾子単位での除外
シリアライズの対象は以下のようなクラス。
package com.rmstar.gson.userguide; public class Example1 { private String v0; static String v1; volatile String v2; transient String v3; static final String v4; static { v1 = "static"; v4 = "constant"; } public Example1() { v0 = "private"; v2 = "volatile"; v3 = "transient"; } }
これを普通にGsonを用いてシリアライズした場合,
{"v0":"private","v2":"volatile"}
となります。
static修飾子とtransient修飾子がついたフィールドは,無視されます。
無視したい修飾子を設定したい場合だとか,
逆にstaticなフィールドを無視したくない場合は,
GsonBuilderでGsonインスタンスを作成する際,
以下のように無視する修飾子を設定することが可能です。
package com.rmstar.gson.userguide; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.lang.reflect.Modifier; public class ExcludingFields1 { public static void main(String[] args) { Gson gson; Example1 ex1 = new Example1(); System.out.println("===Exclude Private==="); gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.PRIVATE) .create(); System.out.println(gson.toJson(ex1)); System.out.println("===Exclude Static==="); gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.STATIC) .create(); System.out.println(gson.toJson(ex1)); System.out.println("===Exclude Volatile and Transient==="); gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.VOLATILE | Modifier.TRANSIENT) .create(); System.out.println(gson.toJson(ex1)); System.out.println("===Exclude Constant==="); gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC) .create(); System.out.println(gson.toJson(ex1)); } }
実行結果は,以下の通りです。
===Exclude Private=== {"v1":"static","v2":"volatile","v3":"transient","v4":"constant"} ===Exclude Static=== {"v0":"private","v2":"volatile","v3":"transient"} ===Exclude Volatile and Transient=== {"v0":"private","v1":"static","v4":"constant"} ===Exclude Constant=== {"v0":"private","v2":"volatile","v3":"transient"}
次に,@Exposeアノテーションを用いての除外
@Exposeアノテーションフィールを用いれば,
フィールド単位でシリアライズ・デシリアライズするフィールドを指定出来ます。
Gsonのインスタンス化を
new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
のように行った場合,
@Exposedアノテーションがついたフィールドのみ
シリアライズ・デシリアライズされます。
package com.rmstar.gson.userguide; import com.google.gson.annotations.Expose; public class Example2 { @Expose private final String expose; private final String notExpose; public Example2() { expose = "expose"; notExpose = "not expose"; } }
このようなクラスをシリアライズします。
package com.rmstar.gson.userguide; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class ExcludingFields2 { public static void main(String[] args) { Gson gson; Example2 ex2 = new Example2(); gson = new Gson(); System.out.println(gson.toJson(ex2)); gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .create(); System.out.println(gson.toJson(ex2)); } }
実行結果は,以下のようになります。
{"expose":"expose","notExpose":"not expose"} {"expose":"expose"}
独自に定義するExclusion Strategyによる除外を紹介します。
package com.rmstar.gson.userguide; import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; public class MyExclusionStrategy implements ExclusionStrategy { private final Class<?> mTypeToSkip; public MyExclusionStrategy(Class<?> typeToSkip) { mTypeToSkip = typeToSkip; } @Override public boolean shouldSkipClass(Class<?> arg0) { return (arg0.equals(mTypeToSkip)); } @Override public boolean shouldSkipField(FieldAttributes arg0) { return false; } }
このようにExclusionStrategyインターフェースを実装したクラスを独自で定義して,
package com.rmstar.gson.userguide; import com.google.gson.ExclusionStrategy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class ExcludingFields3 { public static void main(String[] args) { Person person = new Person("Alice", 25); ExclusionStrategy strategy; Gson gson; strategy = new MyExclusionStrategy(String.class); gson = new GsonBuilder() .addSerializationExclusionStrategy(strategy) .create(); System.out.println(gson.toJson(person)); strategy = new MyExclusionStrategy(int.class); gson = new GsonBuilder() .addSerializationExclusionStrategy(strategy) .create(); System.out.println(gson.toJson(person)); } }
実行結果は,以下の通りです。
{"age":25} {"name":"Alice"}
これでも出来ない場合は,自分で細かくカスタマイズすることもできるようです。
それはまた次回にでも。
それでは,また会えることを祈りつつ。