强类型与RESTful API:Kotlin中如何定义GET请求返回对象?
嗨,作为Kotlin新手,从Python的灵活字典切换到强类型的Kotlin,有这个疑问太正常啦!咱们直接说结论:
1. 是否必须定义与JSON输出完全匹配的类?
完全不需要。Kotlin的主流序列化库(比如Kotlinx Serialization、Jackson)都支持只处理你关心的字段,多余的字段会被自动忽略,不用强迫自己把API返回的所有字段都塞进数据类里。
2. 能否跳过部分字段,只保留需要的字段?
当然可以!这其实是日常开发中非常常见的做法——毕竟很多API返回的字段可能有十几个,但你可能只用到其中两三个。下面给你用两种最常用的库举例子:
示例1:用Kotlinx Serialization(Kotlin官方推荐)
首先确保你的项目里添加了相关依赖(以Gradle为例):
// build.gradle.kts plugins { kotlin("jvm") version "1.9.0" kotlin("plugin.serialization") version "1.9.0" } dependencies { implementation("io.ktor:ktor-client-core:2.3.3") implementation("io.ktor:ktor-client-content-negotiation:2.3.3") implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.3") }
假设API返回的JSON是这样的:
{ "id": 123, "username": "kotlin_newbie", "email": "newbie@example.com", "created_at": "2024-01-01", "is_active": true }
而你只需要id和username这两个字段,那定义数据类的时候只写这两个就行:
import kotlinx.serialization.Serializable @Serializable data class User( val id: Int, val username: String )
然后用Ktor客户端调用API并反序列化:
import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.serialization.kotlinx.json.json import io.ktor.client.request.get import kotlinx.coroutines.runBlocking fun main() = runBlocking { val client = HttpClient { install(ContentNegotiation) { json() } } val user = client.get("https://api.example.com/users/123").body<User>() println("用户ID:${user.id},用户名:${user.username}") client.close() }
Kotlinx Serialization的默认配置就会自动忽略数据类中不存在的字段(比如email、created_at这些),完全不用额外设置。
示例2:用Jackson(Java生态最常用的序列化库)
如果你的项目用Jackson,同样可以轻松实现:
先添加依赖:
// build.gradle.kts dependencies { implementation("com.fasterxml.jackson.core:jackson-databind:2.15.2") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.15.2") }
同样定义只包含需要字段的数据类:
data class User( val id: Int, val username: String )
然后配置Jackson忽略未知字段,并反序列化:
import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.registerKotlinModule import java.net.URL fun main() { val mapper = ObjectMapper() .registerKotlinModule() // 支持Kotlin数据类 .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) // 关键:忽略未知字段 val jsonString = URL("https://api.example.com/users/123").readText() val user = mapper.readValue(jsonString, User::class.java) println("用户ID:${user.id},用户名:${user.username}") }
这里的关键就是FAIL_ON_UNKNOWN_PROPERTIES这个配置,把它设为false,Jackson就不会因为JSON里有数据类没有的字段而报错。
额外小技巧:临时用Map接收(类似Python字典)
如果你只是临时需要查看某个字段,不想定义数据类,也可以直接把JSON反序列化成Map<String, Any>,就像Python里的字典一样:
// 用Kotlinx Serialization的例子 val jsonString = """{"id":123,"username":"kotlin_newbie"}""" val userMap = Json.decodeFromString<Map<String, Any>>(jsonString) println(userMap["id"]) // 输出123
不过这种方式失去了强类型的优势,日常开发还是更推荐用数据类哦。
内容的提问来源于stack exchange,提问作者user331465

