1. 概述

Google Gson 是处理 JSON 数据最流行的 Java 库之一,也广泛用于 Kotlin 项目中。它提供了简单而强大的 API,用于将对象序列化为 JSON 字符串,或将 JSON 字符串反序列化为对象。

本文将介绍如何使用 Gson 在 Kotlin 中处理 JSON 数组的序列化与反序列化,包括处理字段名不一致、字段缺失等常见场景。

2. Google Gson 简介

在 Gson 的语境中:

  • 序列化(Serialization):将 Kotlin 对象转换为 JSON 字符串。
  • 反序列化(Deserialization):将 JSON 字符串解析为 Kotlin 对象。

Gson 提供了对 Kotlin 数据类的良好支持,尤其在处理复杂嵌套结构(如 List、Map 等)时非常方便。

2.1. Maven 依赖

在使用 Gson 之前,需要在 pom.xml 中添加以下依赖:

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

3. 实战示例

我们以作者(Author)和文章(Article)为例,演示如何使用 Gson 解析包含嵌套数组的 JSON 数据。

先定义两个数据类:

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 可以自动将 Kotlin 的 List 转换为 JSON 数组:

@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)
}

如果字段名和 JSON Key 不一致,可以使用 @SerializedName 注解指定:

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

这样序列化时,字段名就会变成 author_articles

示例:

@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. 反序列化数组

反序列化 JSON 数组时,需要使用 TypeToken 来指定泛型类型:

@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<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).anyMatch { a -> a.type == "Technical Editor" }
}

⚠️ 注意:Gson 默认会将缺失字段设为 null,即使 Kotlin 数据类中该字段有默认值也是如此。例如:

@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 }
}

踩坑提醒:如果你期望某些字段即使在 JSON 中不存在也保留默认值,请使用 @Expose 注解并配置 GsonBuilder

4. 总结

本文介绍了如何使用 Gson 在 Kotlin 中处理 JSON 数组的序列化与反序列化,包括:

  • 使用 TypeToken 反序列化泛型数组
  • 使用 @SerializedName 映射不同字段名
  • 处理字段缺失的情况

Gson 是一个轻量且功能强大的 JSON 工具库,适合大多数 Kotlin 项目中的 JSON 处理需求。

完整示例代码请访问:GitHub 项目地址


原始标题:Parsing JSON Arrays in Kotlin with Gson

» 下一篇: Kotlin 教程