1. 简介

JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,广泛应用于前后端通信、微服务间数据传输等场景。作为开发者,我们经常需要从一段 JSON 字符串中提取出某个具体的字段值。

本文将介绍在 Kotlin 中提取 JSON 字符串中单个值的几种常用方式,涵盖主流库的实际用法,并对比其特点,方便你在实际项目中做出合适选择——毕竟踩过才知道哪个坑更深 😄。


2. 使用 Kotlinx Serialization 库

Kotlinx.serialization 是 JetBrains 官方推出的序列化框架,原生支持 Kotlin,无需反射,性能优秀,特别适合纯 Kotlin 项目。

2.1 Maven 和 Gradle 依赖

使用 Maven 时,在 pom.xml 中添加:

<dependency>
    <groupId>org.jetbrains.kotlinx</groupId>
    <artifactId>kotlinx-serialization-json-jvm</artifactId>
    <version>1.6.2</version>
</dependency>

使用 Gradle(Kotlin DSL),在 build.gradle.kts 中添加:

implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.6.2")

提示:如果你使用的是多平台或 Android 项目,请确保引入对应平台的模块。

2.2 实现方式

通过 Json 构造函数创建一个解析器实例。虽然处理 JsonObject 时不需要配置,但建议开启 ignoreUnknownKeys = true,避免后续扩展字段导致反序列化失败。

@Test
fun `extract values from JSON string using Kotlinx serialization`() {
    val json = Json { ignoreUnknownKeys = true }
    val jsonString = "{\"name\":\"John\", \"age\":30, \"city\":\"New York\"}"
    val jsonObject = json.parseToJsonElement(jsonString).jsonObject
    val name = jsonObject["name"]?.jsonPrimitive?.content
    val city = jsonObject["city"]?.jsonPrimitive?.content
    val age = jsonObject["age"]?.jsonPrimitive?.int

    assertEquals("John", name)
    assertEquals("New York", city)
    assertEquals(30, age)
    assertEquals("{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}", jsonObject.toString())
}

📌 核心步骤说明:

  • parseToJsonElement():将字符串解析为 JsonElement
  • .jsonObject:转为 JsonObject 类型
  • ["key"]:通过下标操作符获取对应字段的 JsonPrimitive
  • .content / .int:提取原始值(字符串或整数)

⚠️ 注意:jsonPrimitive?.content 返回的是 String 类型,即使原始是数字;若需类型转换,应使用 .int.double 等属性。


3. 使用 Gson 库

Gson 是 Google 推出的经典 Java JSON 库,兼容性极强,几乎成为 Android 开发的标配。它也完全适用于 Kotlin,尤其适合混合语言项目。

3.1 Maven 和 Gradle 依赖

Maven 配置:

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

Gradle(Kotlin DSL):

implementation("com.google.code.gson:gson:2.10.1")

❌ 踩坑提醒:Gson 对 Kotlin 的 data class 支持有限,特别是默认参数和不可变属性,建议仅用于简单解析场景。

3.2 实现方式

@Test
fun `extract values from JSON string using Gson`() {
    val gson = Gson()
    val jsonString = "{\"name\":\"John\", \"age\":30, \"city\":\"New York\"}"
    val jsonObject = gson.fromJson(jsonString, JsonObject::class.java)
    val name = jsonObject.get("name").asString
    val city = jsonObject.get("city").asString
    val age = jsonObject.get("age").asInt

    assertEquals("John", name)
    assertEquals("New York", city)
    assertEquals(30, age)
    assertEquals("{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}", jsonObject.toString())
}

📌 关键点:

  • fromJson(jsonString, JsonObject::class.java):直接解析为 JsonObject
  • .get("key"):获取 JsonElement
  • .asString / .asInt:安全地转换为目标类型

💡 小技巧:如果字段可能为空,可用 has("key") 先判断是否存在,避免 NPE。


4. 使用 Jackson 库

Jackson 是 Java 生态中最强大的 JSON 处理库之一,性能优异,功能丰富,尤其适合 Spring Boot 项目集成。

4.1 Maven 和 Gradle 依赖

Maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.16.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-kotlin</artifactId>
    <version>2.16.0</version>
</dependency>

⚠️ 注意:必须同时引入 jackson-databindjackson-module-kotlin 才能完整支持 Kotlin 特性(如 data class、默认参数等)。

Gradle(Kotlin DSL):

implementation("com.fasterxml.jackson.core:jackson-databind:2.16.0")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.16.0")

4.2 实现方式

@Test
fun `extract values from JSON string using Jackson library`() {
    val objectMapper = jacksonObjectMapper()
    val jsonString = "{\"name\":\"John\", \"age\":30, \"city\":\"New York\"}"
    val jsonObject = objectMapper.readValue<JsonNode>(jsonString)
    val name = jsonObject.get("name").asText()
    val city = jsonObject.get("city").asText()
    val age = jsonObject.get("age").asInt()
        
    assertEquals("John", name)
    assertEquals("New York", city)
    assertEquals(30, age)
    assertEquals("{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}", jsonObject.toString())
}

📌 核心流程:

  • jacksonObjectMapper():Kotlin 扩展函数,自动配置好 Kotlin 模块
  • readValue<JsonNode>():将字符串读取为树形结构 JsonNode
  • get("field"):获取子节点
  • asText() / asInt():类型提取方法

✅ 优势:支持复杂嵌套结构查询,比如 jsonObject.get("user").get("address").get("zipCode"),非常适合动态解析。


5. 总结

方案 适用场景 优点 缺点
✅ Kotlinx Serialization 纯 Kotlin 项目 零反射、编译期生成、类型安全 学习成本略高,生态相对小
✅ Gson Android / 老旧项目 简单易用、兼容性强 不支持 Kotlin 默认参数,性能一般
✅ Jackson Spring Boot / 微服务 功能强大、性能好、社区活跃 配置稍复杂,依赖较多

📌 最终选择建议:

  • 如果你在写一个现代 Kotlin 服务(尤其是 Ktor 或 Spring Boot + Kotlin),推荐优先使用 Kotlinx Serialization
  • 若项目已重度依赖 Spring,那 Jackson 是最自然的选择
  • 在 Android 上做轻量级 JSON 解析?Gson 依然够用,但注意规避 Kotlin 兼容性问题

所有示例代码均可在 GitHub 获取:https://github.com/Baeldung/kotlin-tutorials/tree/master/kotlin-json


原始标题:How to Extract Individual Values From a JSON String