1. 概要

Google Gsonは、JSONオブジェクトを処理するための最も人気のあるライブラリの1つであり、Kotlinを含む多くの一般的なプログラミング言語がそれをサポートしています。

このチュートリアルでは、Gsonを使用してKotlinでJSON配列をシリアル化および逆シリアル化する方法について説明します。

2. Google Gson

Google Gsonのコンテキストでは、シリアル化は、オブジェクトの状態をJSON表現に変換するためのメカニズムです。 一方、 deserialization は逆のプロセスであり、JSONを使用してメモリ内の実際のオブジェクトを再作成します。

Gsonは、 KotlinのJSONデータバインディングサポートを提供することでこれらのプロセスを処理するのに役立ち、複雑なデータ型を管理するための優れたツールです

2.1. Mavenの依存関係

まず、 GsonMaven依存関係をpom.xmlに追加する必要があります。

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

3. 実装

ケーススタディでは、著者と記事の例を検討します。 1人の著者が複数の記事を持つことができ、1つの記事が1人の著者にのみ属することができます。 Kotlinのデータクラスを利用して、シリアライズ/デシリアライズプロセスを実装します。

まず、Gsonで解析するために使用するArticleクラスとAuthorクラスを作成しましょう。

data class Article(
    var title: String,
    var category: String,
    var views: Int
) {
}
data class Author(
    var name: String,
    var type: String? = null,
    var articles: List<Article>? = null
) {
}

3.1. アレイのシリアル化

Gsonには、配列またはリストとの間でJSONオブジェクトを自動的に解析する、またはその逆の解析機能が組み込まれています。 たとえば、 Author オブジェクトのリストを名前だけで定義し、それをJSON Arrayオブジェクトにシリアル化できます。

@Test
fun serializeObjectListTest() {
    val authors = listOf(
      Author("John", "Technical Author"),
      Author("Jane", "Technical Author"),
      Author("William", "Technical Editor")
    )
    val serialized = Gson().toJson(authors)

    val json =
      """[{"name":"John","type":"Technical Author"},{"name":"Jane","type":"Technical Author"},{"name":"William","type":"Technical Editor"}]"""
    assertEquals(serialized, json)
}

Gsonは、一致しないJSONキーとオブジェクトフィールド名を持つ配列をシリアル化する機能も提供します。 たとえば、別の名前を使用してarticlesリストをシリアル化できます。

data class Author(
    var name: String,
    var type: String? = null,
    @SerializedName("author_articles")
    var articles: List<Article>? = null,
) {
}

その結果、 Article 配列は、異なる名前でシリアル化されて、結果のJSONになります。

@Test
fun serializeObjectListWithNonMatchingKeysTest() {
    val authors = listOf(
        Author(
          "John",
          "Technical Author",
          listOf(Article("Streams in Java", "Java", 3), Article("Lambda Expressions", "Java", 5))
        ),
        Author("Jane", "Technical Author", listOf(Article("Functional Interfaces", "Java", 2))),
        Author("William", "Technical Editor")
    )
    val serialized = Gson().toJson(authors)

    val json =
      """[{"name":"John","type":"Technical Author","author_articles":[{"title":"Streams in Java","category":"Java","views":3},{"title":"Lambda Expressions","category":"Java","views":5}]},{"name":"Jane","type":"Technical Author","author_articles":[{"title":"Functional Interfaces","category":"Java","views":2}]},{"name":"William","type":"Technical Editor"}]"""
    assertEquals(serialized, json)
}

3.2. アレイの逆シリアル化

Gsonを使用してJSON配列を逆シリアル化するには、配列内のすべての要素の汎用型表現が必要です。 したがって、 TokenType コンストラクターを呼び出して、Gsonが評価するオブジェクトをカプセル化する必要があります。

@Test
fun deserializeObjectListTest() {
    val json =
      """[{"name":"John","type":"Technical Author"},{"name":"Jane","type":"Technical Author"},{"name":"William","type":"Technical Editor"}]"""
    val typeToken = object : TypeToken<List>() {}.type
    val authors = Gson().fromJson<List>(json, typeToken)

    assertThat(authors).isNotEmpty
    assertThat(authors).hasSize(3)
    assertThat(authors).anyMatch { a -> a.name == "John" }
    assertThat(authors).anyMatch { a -> a.type == "Technical Editor" }
}

デフォルトでは、GsonはJSON結果オブジェクトの欠落しているフィールドにnull値を設定することに注意することが重要です。 したがって、 Jackson のような他のライブラリでは、デフォルト値を持つクラスでもその動作を期待する必要があります。

ここでは、JSON文字列に配列内のすべての要素のtypeフィールドがありません。

@Test
fun deserializeObjectListWithMissingFieldsTest() {
    val json =
      """[{"name":"John"},{"name":"Jane"},{"name":"William"}]"""
    val typeToken = object : TypeToken<List<Author>>() {}.type
    val authors = Gson().fromJson<List<Author>>(json, typeToken)

    assertThat(authors).isNotEmpty
    assertThat(authors).hasSize(3)
    assertThat(authors).anyMatch { a -> a.name == "John" }
    assertThat(authors).allMatch { a -> a.type == null }
}

4. 結論

このチュートリアルでは、Google Gsonライブラリを使用して、KotlinでJSON配列をシリアル化および逆シリアル化する方法について説明しました。 また、フィールドが欠落しているJSON配列の解析を管理する方法と、JSON配列に使用するカスタムキー名を指定する方法についても説明しました。

いつものように、完全なコードはGitHubから入手できます。