在 Kotlin 中处理 JSON:解析与序列化完全指南
JSON (JavaScript Object Notation) 仍然是现代 Web 开发中最流行的数据交换格式之一。在使用 Kotlin 进行开发时,无论是基于 Ktor 的后端还是 Android 移动应用,高效解析和序列化 JSON 都是一项必备技能。本文将介绍在 Kotlin 中处理 JSON 的三种主要方法:使用 Gson、Moshi 以及 JetBrains 官方解决方案 kotlinx.serialization 库。
为什么 Kotlin 需要特殊的 JSON 处理方法?
Kotlin 是一种静态类型语言,具有 null 安全性、data class 和默认属性等特性。JSON 处理库必须考虑这些特性,以确保代码不仅可用,而且符合语言习惯。配置不当可能导致 NullPointerException 或在反序列化时出现意外行为。
1. 使用 Gson 处理 JSON
Google 的 Gson 是最古老、最流行的库之一。它易于使用,但在与 Kotlin 配合时有一些特殊之处。
添加依赖
// build.gradle.ktsimplementation("com.google.code.gson:gson:2.10.1")将对象序列化为 JSON
import com.google.gson.Gson
data class User( val id: Int, val name: String, val email: String? = null)
fun main() { val user = User(1, "伊万·彼得罗夫", "ivan@example.com") val gson = Gson() val json = gson.toJson(user) println(json) // 输出: {"id":1,"name":"伊万·彼得罗夫","email":"ivan@example.com"}}将 JSON 解析为对象
fun parseUser(jsonString: String): User { val gson = Gson() return gson.fromJson(jsonString, User::class.java)}
fun main() { val json = """{"id":2,"name":"安娜·斯米尔诺娃","email":null}""" val user = parseUser(json) println(user.name) // 安娜·斯米尔诺娃}重要提示: Gson 使用 Java 反射,可能不会考虑 Kotlin 的 null 安全性。在反序列化时,声明为 non-null 的字段可能获得 null 值,从而导致运行时错误。建议使用 @JvmOverloads 和带默认值的构造函数。
2. Moshi — Square 的现代替代方案
Moshi 在设计时考虑了 Kotlin 的特性,提供了与 null 安全性和 data class 更好的集成。
添加依赖
// build.gradle.ktsimplementation("com.squareup.moshi:moshi-kotlin:1.15.0")kapt("com.squareup.moshi:moshi-kotlin-codegen:1.15.0")Moshi 使用示例
import com.squareup.moshi.Moshiimport com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
data class Product( val id: Int, val title: String, val price: Double, val inStock: Boolean = false)
fun main() { val moshi = Moshi.Builder() .addLast(KotlinJsonAdapterFactory()) .build()
val adapter = moshi.adapter(Product::class.java)
// 序列化 val product = Product(101, "笔记本电脑", 89999.99, true) val json = adapter.toJson(product) println(json) // {"id":101,"title":"笔记本电脑","price":89999.99,"inStock":true}
// 反序列化 val jsonString = """{"id":102,"title":"鼠标","price":2500.00}""" val parsedProduct = adapter.fromJson(jsonString) println(parsedProduct?.title) // 鼠标 println(parsedProduct?.inStock) // false (默认值)}Moshi 自动处理 data class 中的默认值,并能正确处理 nullable 类型。为了获得更好的性能,建议使用 @JsonClass 注解进行代码生成。