AndroidのGoogle Gsonの例とチュートリアル.

Gson (Google Gsonとしても知られています) は、JSONオブジェクトをパースして作成するための小さなJavaベースのライブラリです。

それは、JavaオブジェクトをJSONに変換して返すためのシリアル化/非シリアル化ライブラリです。

GoogleはGsonを自社のプロジェクトのために開発しましたが、その後、バージョン1.0からGsonを一般に公開するようになりました。

Gsonは非常に強力で、ソースコードを持たない既存のオブジェクトを含む、任意のJavaオブジェクトを扱うことができます。

Gsonの使用例

  1. JavaオブジェクトのJSONへの変換とその逆。
    1. JSONの文字列を、同等のJavaオブジェクトに変換する。

Gsonが作られた理由

Gsonが作られた理由は以下の通りです。

  1. シンプルな toJson()fromJson() メソッドを提供することによって、JSONを簡単に扱えるようにするためです。これらのメソッドによって、JavaオブジェクトをJSONに変換したり、逆にJSONをJavaオブジェクトに変換したりすることができます。
    1. 既存の変更不可能なオブジェクトをJSONに変換したり、JSONから変更したりすることができるようにする。
    1. Java Genericsを幅広くサポートする。
    1. オブジェクトのカスタム表現を可能にする
  2. 任意の複雑なオブジェクトのサポート (深い継承階層とジェネリック型の広範な使用)

Gsonのインストール

Gsonは、androidを含むJavaベースのプロジェクトを対象としています。つまり、ビルドシステムに応じて、少なくともいくつかのインストール方法があります。

(a) Gradle

例えば、あなたがandroidを使用している場合、おそらくandroid studioとgradleを使用していることでしょう。

その場合、アプリレベルのbuild.gradleのdependenciesに以下を追加します。

implementation 'com.google.code.gson:gson:2.8.5'

(b) Maven

一般的なJavaプロジェクトを作成する場合は、Mavenを使用することが多いでしょう。

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

(c) Jar

最後の方法は、jarを直接使用する方法です。Maven Centralからダウンロードし、プロジェクトに追加します。

Jarのダウンロードはこちら](https://maven-badges.herokuapp.com/maven-central/com.google.code.gson/gson)。

重要なクラス

(a) Gson

Gson は com.google.gson パッケージに含まれるクラスで、Gson ライブラリを使用するために必要なメインクラスです。

通常は、まず Gson のインスタンスを生成し、そのインスタンスに対して toJson(Object)fromJson(String, Class) メソッドを呼び出して使用します。

(b). JsonElement

JsonElementcom.google.gson` パッケージに含まれるクラスで、Json の要素を表します。

以下は、JsonElementのオブジェクトです。

  1. JsonObject`
  2. JsonArray`
  3. JsonPrimitive`
  4. JsonNull` です。
(c) JsonObject

JsonObjectcom.google.gson` パッケージに含まれるクラスで、Json のオブジェクト型を表現します。

このオブジェクトは、名前と値のペアで構成され、名前は文字列、値は他の任意の JsonElement 型になります。

これによって、JsonElementのツリーを構築することができます。これらの要素は、追加された順番に管理されます。

(d) JsonParser

JsonParsercom.google.gson` パッケージに含まれるクラスで、Json をパースして JsonElement のパースツリーを作成するために使用されます。

Gsonの作成

1. Gson()

Gsonオブジェクトを作成する最初の方法は、defaluコンストラクタである Gson() を使用することです。

これは、デフォルトの構成でGsonオブジェクトを構築します。

このデフォルトの構成は以下の通りです。

    1. toJsonメソッドで生成されるJSONはコンパクトに表現されます。これは、不要なホワイトスペースがすべて取り除かれることを意味します。この動作は GsonBuilder#setPrettyPrinting() で変更することができます。
    1. 生成されたJSONは、NULLのフィールドをすべて削除します。配列は順序付きリストであるため、配列内のNULLはそのまま保持されることに注意してください。さらに、あるフィールドがNULLでなくても、生成されるJSONが空であれば、そのフィールドは保持されます。GsonBuilder#serializeNulls() を設定することで、Null 値をシリアライズするように Gson を設定することができます。
    1. Gson は、Enums、Map、java.net.URL、java.net.URI、java.util.Locale、java.util.Date、java.math.BigDecimal および java.math.BigInteger クラスのデフォルトシリアライズとデシリアライズを提供 します。
2. GsonBuilder

GsonBuilder` は、Gson を様々な設定でインスタンス化するために使用される。

Gson gson = new GsonBuilder().setPrettyPrinting().create();

GsonBuilderはビルダーパターンに従っており、典型的には、最初に様々なコンフィギュレーションメソッドを呼び出して希望のオプションを設定し、最後に create() メソッドを呼び出すことで使用されます。

Gsonの重要なメソッド

toJson() (a).

このメソッドは、指定されたオブジェクトを、汎用型のものも含めて、同等のJson表現にシリアライズする。

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

指定されたオブジェクトが汎用型の場合、必ず使用しなければならない。非ジェネリックなオブジェクトの場合は、代わりに toJson(Object,Appendable) を使用します。

fromJson (b)。

このメソッドは、指定されたJsonを指定された型のオブジェクトにデシリアライズします。このメソッドは、指定されたオブジェクトが汎用的な型である場合に有用です。汎用的でないオブジェクトの場合は、代わりに fromJson(String,Class) を使用します。

JsonをStringではなくReaderで持っている場合は、代わりに fromJson(Reader,Type) を使います。

(c). toJsonTree (日本語)

説明: 指定されたオブジェクト(汎用型を含む)を、JsonElements の木構造として等価な表現にシ リアライズする。このメソッドは、指定されたオブジェクトが汎用型の場合に使用しなければなりません。非ジェネリックオブジェクトの場合は、代わりに toJsonTree(Object) を使用する。

getAdapter 型のアダプタを返します。

型に対応する型アダプタを返します。

完全な Gson Hello World の例

Gson による完全なハローワールドの例を見てみましょう。Gson がインストールされていれば、この例をあなたの IDE にコピーペーストして実行できます。

import com.google.gson.Gson;

/**
 *  Gson Hello World
 *
  */
public class GsonHelloWorld {

    public static void main(String[] args) {
        // init class
        Place place = new Place();
        place.setName("World");

        Human human = new Human();
        human.setMessage("Hi");
        human.setPlace(place);

        // convert to json
        Gson gson = new Gson();
        String jsonString = gson.toJson(human);
        System.out.println("json " + jsonString); // print "json {"message":"Hi","place":{"name":"World"}}"

        // convert from json
        Human newHuman = gson.fromJson(jsonString, Human.class);
        newHuman.say(); // print "Hi , World!"
    }

    private static class Human {
        private String message;
        private Place place;

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public Place getPlace() {
            return place;
        }

        public void setPlace(Place place) {
            this.place = place;
        }

        public void say() {
            System.out.println();
            System.out.println(getMessage() + " , " + getPlace().getName() + "!");
        }
    }

    private static class Place {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

GSON の簡単な例とハウツー

これらの例では、Google Gsonを使用しています。

1. マップをJSONに変換する方法

例えば、文字列のキーとTの値を持つマップを渡したとする。そして、それをマップするか、JSONの文字列に変換するように指示します。

どうやるんだ?

Gson クラスの toJson() メソッドを使用することができます。まずは Gson` クラスをインスタンス化して、そのメソッドを呼び出してください。

    public static <T> String mapToJsonStr(Map<String, T> map) {
        Gson gson = new Gson();
        return gson.toJson(map);
    }
2. JSONをMapに変換する方法

JSONの文字列があったとして、それをMapのデータ構造に変換してほしいと言われたらどうしますか。

その場合は GsonfromJson() メソッドを使用します。

しかし、今回は Map をジェネリックパラメータとして TypeToken をインスタンス化しなければなりません。そして、 fromJson() メソッドの最初のパラメータとして、json 文字列を渡します。そして、Type のインスタンスを2番目のパラメータとして渡します。

    public static <T> Map<String, T> jsonStrToMap(String jsonStr) {
        Gson gson = new Gson();
        Type type = new TypeToken<Map<String, T>>() {
        }.getType();
        return gson.fromJson(jsonStr, type);
    }
3. JSONをオブジェクトに変換する方法

さて、JSONの文字列があり、それを指定された型のObjectに変換するように言われました。

この場合も、fromJson()`メソッドにJSON文字列と型を渡します。

    public static <T> T jsonToObj(String jsonStr, Class<T> classOfT) {
        return new Gson().fromJson(jsonStr, classOfT);
    }
4. JSONをArrayListに変換する方法

多くのプロジェクトでよくあるシナリオは、jsonの文字列を最もよく使われるコレクションであるArrayListに変換することです。

まず、 TextUtilsisEmpty() メソッドを使用して、空の値があるかどうかをチェックします。

次に、JSONObject の ArrayList をジェネリックタイプとして渡して、 TypeToken インスタンスを取得します。

次に、fromJson() メソッドを使用して、JSONObject の ArrayList を取得します。

そして、それをループして、入力したい ArrayList を埋めることができます。

    public static <T> ArrayList<T> jsonToArrayList(String json, Class<T> clazz) {
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        Type type = new TypeToken<ArrayList<JsonObject>>() {
        }.getType();
        ArrayList<JsonObject> jsonObjects = new Gson().fromJson(json, type);

        ArrayList<T> arrayList = new ArrayList<>();
        for (JsonObject jsonObject : jsonObjects) {
            arrayList.add(new Gson().fromJson(jsonObject, clazz));
        }
        return arrayList;
    }
5. リストをJSONに変換する方法

もうひとつよくあるのが、Listをjsonの文字列に変換することです。リストをシリアライズしてWhereに送りたいとか、APIとして公開する基本的な方法かもしれません。

この場合も、toJson() メソッドが簡単にそれをやってくれます。

    public static <T> String listToJson(List<T> list) {

        Gson gson = new Gson();
        String jsonstring = gson.toJson(list);
        return jsonstring;

    }
6. オブジェクトからJSONへの変換方法

オブジェクトを持っていて、それをJSONに変換する場合は、オブジェクトをパラメータとして toJson() メソッドを呼び出すだけでよいでしょう。

    public static <T> String object2Json(T t) {
        Gson gson = new Gson();
        return gson.toJson(t);
    }
7. アノテーションを使わずに特定のフィールドをシリアライズから除外する方法

通常、Gsonではアノテーションによってインクルードするフィールドを制御します。しかし、アノテーションを使わずに、特定のフィールドをシリアライズから除外することは可能です。

Gson gson = new GsonBuilder()
   .setExclusionStrategies(new TestExclStrat())
   //.serializeNulls() <-- uncomment to serialize NULL fields as well
   .create();
 Student src = new Student();
 String json = gson.toJson(src);
 System.out.println(json);

[参考】(http://stackoverflow.com/a/4803346#1#L0)

8. Gsonでプリティプリントする方法

プリティプリントとは、JSONデータをより読みやすくするために空白を追加することです。GsonBuilder#setPrettyPrinting()`を利用することができます。

Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(uglyJSONString);
String prettyJsonString = gson.toJson(je);

[参考】(http://stackoverflow.com/a/7310424#0#L0)

9. TreeModelを使ったJSONの書き方

ここからが重要なメソッドです。jsonデータを読み書きするためのメソッドを2つ用意しています。

以下がそのクラス全体です。


import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import java.io.IOException;

public class TreeModel {
    public static void main(String[] args) throws IOException {
        System.out.print("readJson: ");
        readJson();
        System.out.println();
        System.out.print("writeJson: ");
        writeJson();
    }

    /**
     *  Example to readJson using TreeModel
     */
    private static void readJson() throws IOException {
        JsonParser parser = new JsonParser();
        JsonElement jsonElement = parser.parse("{"message":"Hi","place":{"name":"World!"}}");
        JsonObject rootObject = jsonElement.getAsJsonObject();
        String message = rootObject.get("message").getAsString(); // get property "message"
        JsonObject childObject = rootObject.getAsJsonObject("place"); // get place object
        String place = childObject.get("name").getAsString(); // get property "name"
        System.out.println(message + " " + place); // print "Hi World!"*/
    }

    /**
     * Example to writeJson using TreeModel
     */
    private static void writeJson() throws IOException {
        JsonObject rootObject = new JsonObject();
        rootObject.addProperty("message", "Hi");
        JsonObject childObject = new JsonObject();
        childObject.addProperty("name", "World!");
        rootObject.add("place", childObject);

        Gson gson = new Gson();
        String json = gson.toJson(rootObject);
        System.out.println(json); // print "{"message":"Hi","place":{"name":"World!"}}"
    }
}
10. 文字列をオブジェクトに変換する方法

Gson myGson = new GsonBuilder().setPrettyPrinting().create();
myGson.fromJson(jsonString, Person.class)
11. JSON文字列をきれいに印刷する

private static String pretty(String json) {
  JsonElement gson = new JsonParser().parse(json);
  return new GsonBuilder().setPrettyPrinting().serializeNulls().create().toJson(gson);
 }
}
12. Gsonを使ったストリーミングAPIの読み書き

JSON Streaming APIの読み書きの例です。JsonReader、JsonToken、JsonWriterの各クラスを使用します。

メソッド main()readJSON() メソッド、writeJson() メソッドを用意しました。

import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.*;
import java.nio.charset.Charset;

public class StreamingAPI {
    public static void main(String[] args) throws IOException {
        System.out.print("readJson: ");
        readJson();
        System.out.println();
        System.out.print("writeJson: ");
        writeJson();
    }

    /**
     *  Example to readJson using StreamingAPI
     */
    private static void readJson() throws IOException {
        String str = "{"message":"Hi","place":{"name":"World!"}}";
        InputStream in = new ByteArrayInputStream(str.getBytes(Charset.forName("UTF-8")));
        JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
        while (reader.hasNext()) {
            JsonToken jsonToken = reader.peek();
            if(jsonToken == JsonToken.BEGIN_OBJECT) {
                reader.beginObject();
            } else if(jsonToken == JsonToken.END_OBJECT) {
                reader.endObject();
            } if(jsonToken == JsonToken.STRING) {
                System.out.print(reader.nextString() + " "); // print Hi World!
            } else {
                reader.skipValue();
            }
        }
        reader.close();
    }

    /**
     * Example to writeJson using StreamingAPI
     */
    private static void writeJson() throws IOException {
        OutputStream outputStream = new ByteArrayOutputStream();
        JsonWriter writer = new JsonWriter(new OutputStreamWriter(outputStream, "UTF-8"));
        writer.beginObject(); // main object
        writer.name("message");
        writer.value("Hi");
        writer.name("place"); // save object Place
        writer.beginObject();
        writer.name("name");
        writer.value("World!");
        writer.endObject();
        writer.endObject();
        writer.close();
        System.out.println(outputStream.toString()); // print "{"message":"Hi","place":{"name":"World!"}}"
    }
}
13. 完全再利用可能なGsonユーティリティクラス

ublic class GsonUtils {

    privatestaticfinaldoubleVERSION=1.0f;
    private static final Gson sGson = createGson(true, false);

    private static final Gson sGsonExpose = createGson(true, true);

    private GsonUtils () {
        thrownewAssertionError();
    }

    /**
     * Create the standard {@link Gson} configuration
     *
     * @return created gson, never null
     */
    public static Gson createGson() {
        return createGson(true, false);
    }

    /**
     * Create the standard {@link Gson} configuration
     *
     * @param serializeNulls whether nulls should be serialized
     * @return created gson, never null
     */
    private static Gson createGson(final boolean serializeNulls,
                                   final boolean exposeEnable ) {
        final GsonBuilder builder = new GsonBuilder ();
        if (serializeNulls) {
            builder.serializeNulls();
        }
        builder . setVersion ( VERSION );
        // json format
        // builder.setPrettyPrinting();
        if (exposeEnable) {
            builder.excludeFieldsWithoutExposeAnnotation();
        }
        return builder.create();
    }

    /**
     * Get reusable pre-configured {@link Gson} instance
     *
     * @return Gson instance
     */
    public static Gson getGson() {
        return sGson;
    }

    /**
     * Get reusable pre-configured {@link Gson} instance
     *
     * @return Gson instance
     */
    public static Gson getGson(final boolean exposeEnable) {
        return exposeEnable ? sGsonExpose : sGson;
    }

    /**
     * Convert object to json, only exports attributes that have been annotated with @Expose
     *
     * @param object
     * @return json string
     */
    public static String toJson(final Object object) {
        return toJson(object, true);
    }

    /**
     * Convert object to json
     *
     * @param object
     * @param exposeEnable Whether to export only @Expose annotated properties, true is only exported by @Expose
     * @return json string
     */
    public static String toJson(final Object object,
                                final boolean exposeEnable ) {
        return exposeEnable ? sGsonExpose.toJson(object) : sGson.toJson(object);
    }

    /**
     * Convert string to given type
     *
     * @param json
     * @param type
     * @return instance of type
     */
    public static <V> V fromJson(String json, Class<V> type) {
        return sGson.fromJson(json, type);
    }

    /**
     * Convert string to given type
     *
     * @param json
     * @param type
     * @return instance of type
     */
    public static <V> V fromJson(String json, Type type) {
        returnsGson.fromJson(json,type);
    }

    /**
     * Convert content of reader to given type
     *
     * @param reader
     * @param type
     * @return instance of type
     */
    public static <V> V fromJson(Reader reader, Class<V> type) {
        return sGson.fromJson(reader, type);
    }

    /**
     * Convert content of reader to given type
     *
     * @param reader
     * @param type
     * @return instance of type
     */
    public static <V> V fromJson(Reader reader, Type type) {
        returnsGson.fromJson(reader,type);
    }

    /**
     * Convert object object to map only supports basic types
     *
     * @param src
     * @param exposeEnable
     * @return
     */
    public static HashMap<String, String> toMap(Object src, boolean exposeEnable) {
        Gson gson = exposeEnable ? sGsonExpose : sGson;
        HashMap<String, String> params = new HashMap<String, String>();
        try {
            if (src == null) {
                return null;
            }
            JsonElement jsonTree = gson . toJsonTree ( src );
            JsonObject jsonObj = jsonTree.getAsJsonObject();
            Iterator<Entry<String, JsonElement>> iterator = jsonObj.entrySet().iterator();
            String curKey;
            JsonElement curVal ;
            while (iterator.hasNext()) {
                Entry<String, JsonElement> entry = iterator.next();
                curKey = entry.getKey();
                curVal = entry.getValue();
                if (!curVal.isJsonNull()) {
                    params.put(curKey, curVal.getAsString());
                }
            }
            return params;
        } Catch ( Exception e ) {
            e . printStackTrace ();
        }
        returnparams;
    }

    public static <T> String mapToJson(Map<String, T> map) {
        Gson gson =  new  Gson ();
        return gson . toJson (folder);
    }
}

Categorized in: