You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Retrofit2+Kotlinx Serialization反序列化遇JsonDecodingException求助

问题解决:Retrofit2 + Kotlinx Serialization 反序列化异常

核心错误分析

  1. JSON结构与数据模型不匹配:JSON响应中data是数组([]),但你的MarsPhoto类中data字段定义为单个Eta对象,这会直接导致解码时期望对象却读取到数组,触发JsonDecodingException。
  2. 类型不匹配:JSON里的service_type是整数类型(如1),但Eta类中该字段定义为String,后续会引发类型转换错误。
  3. 异常信息中的EOF是结构不匹配导致解析中断后出现的附加提示,核心问题还是模型结构错误。

修正后的代码模型

根模型类

@Serializable
data class MarsPhoto(
    val type: String = "", // 返回数据对应的API标识
    val version: String = "", // 返回JSON的版本号
    val generated_timestamp: String = "", // 响应初始生成时间戳(缓存前)
    val data: List<Eta> // 修改为List<Eta>,匹配JSON数组结构
)

ETA数据类

@Serializable
data class Eta(
    val co: String = "KMB", // 公交公司
    val route: String = "", // 公交线路编号
    val dir: String = "", // 线路方向
    val service_type: Int = 0, // 修改为Int类型,对应JSON中的整数
    val seq: Int = 0, // 站点序号
    val dest_tc: String = "", // 繁体中文目的地
    val dest_sc: String = "", // 简体中文目的地
    val dest_en: String = "", // 英文目的地
    val eta_seq: Int = 0, // ETA序号
    val eta: String = "-", // 下一班次时间戳
    val rmk_tc: String = "", // 繁体中文备注
    val rmk_sc: String = "", // 简体中文备注
    val rmk_en: String = "", // 英文备注
    val data_timestamp: String = "" // 数据初始生成时间戳
)

额外优化建议

如果希望更规范地处理时间戳,可以引入kotlinx serialization的时间序列化扩展,将时间字段类型改为Instant:

  1. 添加依赖(build.gradle.kts):
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.6.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.1")
  1. 自定义序列化器并修改字段:
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

object InstantAsStringSerializer : kotlinx.serialization.KSerializer<Instant> {
    override val descriptor: SerialDescriptor = String.serializer().descriptor

    override fun deserialize(decoder: Decoder): Instant {
        return Instant.parse(decoder.decodeString())
    }

    override fun serialize(encoder: Encoder, value: Instant) {
        encoder.encodeString(value.toString())
    }
}

// 在数据类中使用示例:
@Serializable(with = InstantAsStringSerializer::class)
val generated_timestamp: Instant = Instant.DISTANT_PAST

内容的提问来源于stack exchange,提问作者Dwill James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 04:40:27