Gson — 这是什么,适用于 Java 和 Kotlin 的 JSON 库

作者: IT Sectr 发布日期: 2026-03-15 阅读时间: 8 分钟

Gson — 来自 Google 的库,用于将 Java 对象序列化为 JSON 以及反向转换,广泛用于 Android 开发。它可以将复杂的对象图转换为紧凑的 JSON 字符串,无需手动编写解析器。根据 Google Gson, 2024 的数据,该库在 GitHub 上拥有超过 23,000 颗星,并且仍然是 Java 和 Kotlin 生态系统中处理 JSON 的最流行解决方案之一。

要点

  • Gson — Google 用于 Java 和 Kotlin 中 JSON 序列化的库
  • fromJson — 将 JSON 反序列化为任何类型的 Java 对象
  • toJson — 将对象序列化为 JSON 字符串
  • @SerializedName — 用于将 JSON 键绑定到类字段的注解
  • TypeToken — 处理泛型和参数化类型

什么是 Gson

Gson — 是由 Google 开发的 Java 库,用于将对象转换为 JSON 表示形式以及反向转换。它使用反射来分析类的结构,从而无需预先配置即可工作。Gson 支持任意 Java 对象、集合、数组、泛型和嵌套类。该库基本使用不需要注解,但提供了注解以实现精细调整。反射的主要缺点是在初始化时性能下降以及在编译阶段无法优化,这在 Android 应用程序冷启动时反序列化数百个模型时尤其明显。尽管如此,Gson 凭借其稳定性和广泛的文档,仍然是大多数项目的可靠选择。

历史和在生态系统中的地位

Gson 由 Google 于 2008 年发布,并迅速成为 Android 应用程序中 JSON 的事实标准。在 Moshi 和 kotlinx.serialization 出现之前,Gson 一直是 Kotlin 项目唯一流行的选择。连接简单 — 在 build.gradle 中添加一个依赖项 — 且没有强制注解,使得 Gson 在各个级别的开发人员中都很受欢迎。

groovy
// 在 build.gradle 中添加 Gson
dependencies {
    implementation 'com.google.code.gson:gson:2.10.1'
}

// 基本用法
data class User(
    val id: Int,
    val name: String,
    val email: String
)

val gson = Gson()
val user = User(1, "John", "john@test.com")
val json = gson.toJson(user)
println(json) // {"id":1,"name":"John","email":"john@test.com"}

除了基本序列化之外,Gson 还提供 GsonBuilder 用于配置行为:日期格式化、禁用 HTML 转义、键注册和自定义实例。GsonBuilder 还允许为库无法自动处理的类型注册自定义 JsonSerializer 和 JsonDeserializer。配置的灵活性使 GsonBuilder 成为在现代 Android 开发中将库适配到项目特定要求时不可或缺且有用的工具。

基本操作 toJson 和 fromJson

toJson 通过反射分析其字段将 Java 对象转换为 JSON 字符串。默认情况下,Gson 包含除 transient 和 static 之外的所有字段。该方法支持所有类型:基本类型、对象、集合和数组。fromJson 执行反向转换,接收 JSON 字符串和目标对象的类,并返回一个字段已填充的实例。

将对象转换为 JSON

在序列化期间,Gson 递归遍历对象的所有字段,包括嵌套字段。循环引用会导致 StackOverflowError,因此必须通过 @Expose 注解或自定义适配器排除。对于集合,Gson 保留元素的类型,但在对带有泛型的列表进行反序列化时,需要 TypeToken 来保留类型信息。

kotlin
// 带有嵌套对象的 data class
data class Address(
    val city: String,
    val street: String
)

data class Employee(
    val id: Int,
    val name: String,
    val address: Address
)

val gson = Gson()
val employee = Employee(1, "Alice",
    Address("New York", "5th Ave"))

// 序列化为 JSON
val json = gson.toJson(employee)

// 从 JSON 反序列化
val jsonString = """
{"id":2,"name":"Bob","address":{"city":"London","street":"Baker St"}}
"""
val parsed = gson.fromJson(jsonString, Employee::class.java)

注解和配置

Gson 提供了一组用于管理序列化过程的注解。@SerializedName 指定与字段名称不同的 JSON 键名称。@Expose 管理字段是否包含在序列化中:通过 GsonBuilder.excludeFieldsWithoutExposeAnnotation() 创建的 Gson 将只处理带有 @Expose 的字段。@Since 和 @Until 控制字段的版本管理。

@SerializedName 和 @Expose

@SerializedName 注解解决了名称不匹配的问题:服务器可能使用 snake_case,而代码中采用 camelCase。该注解接受一个值和可选的备选方案以实现向后兼容。@Expose 允许通过将敏感字段(密码、令牌)标记为 @Expose(serialize = false) 来将其从序列化中隐藏。除了包含和排除之外,@Expose 可以与 GsonBuilder.excludeFieldsWithoutExposeAnnotation 结合使用,创建字段的白名单,这有助于在序列化具有大量字段的对象时控制攻击面。

kotlin
// 带有 Gson 注解的模型
data class UserResponse(
    @SerializedName("user_id")
    val userId: Int,

    @SerializedName("full_name",
        alternate = [Alternative("name")])
    val fullName: String,

    @Expose(serialize = false)
    val password: String
)

// 带有 @Expose 过滤的 Gson
val gson = GsonBuilder()
    .excludeFieldsWithoutExposeAnnotation()
    .setPrettyPrinting()
    .create()

val user = UserResponse(1, "John", "secret123")
println(gson.toJson(user))
// {"user_id":1,"full_name":"John"} — password excluded

处理泛型

泛型的问题 在于 Java 和 Kotlin 中编译期间的类型擦除。当 Gson 反序列化 List<User> 时,它不知道元素的类型并返回 List<Map<String, Any>>。为了保留类型信息,Gson 提供了 TypeToken — 一个通过匿名类捕获类型参数的抽象类。如果没有 TypeToken,开发人员必须手动将每个元素从 Map 转换为目标类型,这会导致代码冗长和性能损失。

用于列表的 TypeToken

TypeToken 解决了类型擦除的问题。开发人员创建一个具有所需类型参数的匿名 TypeToken 子类,Gson 使用类签名中的信息进行正确的反序列化。TypeToken 也适用于 Map、Set 和任何其他参数化类型,包括嵌套的泛型。特别是,对于 Map<String, List<User>>,需要具有完整嵌套类型签名的 TypeToken,否则 Gson 会将值反序列化为 List<Map<String, Any>> 而不是 List<User>。

kotlin
// 用于列表反序列化的 TypeToken
data class Product(
    val id: Int,
    val title: String,
    val price: Double
)

val jsonArray = """
[
    {"id":1,"title":"Phone","price":599.0},
    {"id":2,"title":"Laptop","price":1299.0}
]
"""

val gson = Gson()
val listType = object : TypeToken<List<Product>>() {}
val products: List<Product> =
    gson.fromJson(jsonArray, listType.type)

// 自定义反序列化器
class LocalDateAdapter :
    JsonDeserializer<LocalDate> {

    override fun deserialize(
        json: JsonElement,
        typeOfT: java.lang.reflect.Type,
        context: JsonDeserializationContext
    ): LocalDate {
        return LocalDate.parse(json.asString)
    }
}

对于自定义序列化逻辑,Gson 支持 JsonSerializerJsonDeserializer 接口。它们通过 GsonBuilder.registerTypeAdapter() 注册,允许处理库无法自动序列化的类型:Java 8 日期、具有非标准值的 Enum 或无法访问源代码的第三方类。实现适配器时,监控性能很重要:在自定义适配器内部调用反射会抵消手动管理的优势,因此首选直接的方法和字段调用。Gson 生态系统中还有 gson-extras 模块,它为常见类型提供适配器,例如 UUID、Optional 和 Joda-Time 日期类型。

通过 GsonBuilder 进行配置

GsonBuilder 提供了数十种用于精细调整序列化的方法。setPrettyPrinting 为输出 JSON 添加缩进和换行以提高可读性。disableHtmlEscaping 禁用字符串中 HTML 字符的转义。setDateFormat 设置日期格式,这对于使用非标准时间表示的服务器至关重要。setLenient 启用宽松的解析模式,忽略某些 JSON 格式错误。addDeserializationExclusionStrategy 允许基于自定义策略以编程方式从反序列化中排除字段。对于调试,setPrettyPrinting 方法结合日志记录非常有用 — 它使 JSON 响应在日志中可读,并简化了不一致性的查找。

GsonBuilder 的一个重要功能是通过 @Since 和 @Until 注解管理字段版本控制。开发人员通过 setVersion 指定对象的版本,Gson 根据字段的版本注解自动包含或排除字段。这在 API 演进中很有用,当同一个模型用于不同版本的服务器协议时。GsonBuilder 还支持注册 TypeAdapterFactory 以全局处理类型系列,以及 complexMapKeySerialization 以正确处理复杂的 Map 键。

常见问题

在 Android 开发中什么是 Gson?

Gson — 是 Google 用于将 Java 对象转换为 JSON 以及反向转换的库。它广泛用于 Android 应用程序中解析服务器响应、序列化请求和将数据保存到本地存储。

Gson 如何处理 null 值?

默认情况下,Gson 在序列化时会跳过为 null 的字段。要启用 null 值,请使用 GsonBuilder.serializeNulls()。在反序列化时,JSON 中缺少的字段保持为 null 或采用该类型的默认值。

Gson 与 Moshi 有何不同?

Moshi 不为 Kotlin 类使用反射,这提供了更高的性能和可预测的行为。Moshi 也正确处理 Kotlin 的空安全,而 Gson 可以将 null 反序列化到非空字段,导致异常。

Gson 中的 @SerializedName 如何工作?

@SerializedName 在名称不匹配时将 JSON 键绑定到类的字段。例如,对于字段 kotlinName 和 JSON 键 “kotlin_name”,注解 @SerializedName(“kotlin_name”) 确保正确的转换。

Gson 中的 TypeToken 是什么?

TypeToken — 是一个通过匿名类捕获类型参数的抽象类。它对于反序列化集合和其他参数化类型是必需的,因为由于类型擦除,Gson 无法在运行时恢复元素的类型。

总结

  • Gson — Google 用于 JSON 序列化的库,支持 Java 和 Kotlin
  • toJson 和 fromJson — 用于序列化和反序列化对象的主要方法
  • @SerializedName — 在名称不匹配时将字段与 JSON 键匹配的注解
  • @Expose — 通过 GsonBuilder 在序列化期间管理字段可见性
  • TypeToken — 针对参数化集合的类型擦除问题的解决方案
  • GsonBuilder — 格式化、版本控制、日期和自定义适配器的配置
  • JsonSerializer/JsonDeserializer — 用于处理具有非标准逻辑的类型的接口

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读