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

请求体传入非可空类型null时Kotlin NPE问题排查

问题原因分析与解决方案

核心原因

kotlinx.serialization的默认配置不会对集合内的非空元素做运行时null校验,但会对顶级非空属性做校验,这就导致了两种场景的差异:

  1. 顶级非空属性的null校验
    当你把RequestBody中的ids设为非可空Ids时,反序列化时传入"ids": null,kotlinx.serialization会直接触发反序列化错误——因为它会检查顶级非空属性的赋值是否符合非空约束,这是默认启用的校验逻辑。
  2. 集合内非空元素的null校验缺失
    你声明的include: List<String>? = null中,String是非可空类型,但默认配置下,kotlinx.serialization不会校验集合内的元素是否为null。当JSON请求体传入include: [null]时,序列化库会直接把null值塞进List<String>集合中(JVM类型擦除导致编译期无法检测),反序列化过程不会报错,但此时你得到的List<String>实际上包含了null元素,违反了Kotlin的非空契约。

序列化时触发NPE的原因

当你调用jsonSerializer.encodeToJsonElement(ids)时,序列化器会遍历include集合中的元素,使用StringSerializer序列化每个元素。StringSerializer的serialize方法要求传入非空的String,但集合中存在null值,直接触发NullPointerException——这就是错误信息中提到的“Parameter specified as non-null is null”的原因。

为什么看起来不符合Kotlin文档的NPE诱因?

Kotlin文档中列出的NPE诱因大多是语言层面的(比如显式调用!!、Java代码传入null等),而这个问题是序列化库的默认配置导致的非空契约违反:kotlinx.serialization默认没有启用集合元素的非空校验,绕过了Kotlin的编译期非空检查,在运行时生成了持有null的非空类型实例,最终在序列化时触发NPE。

解决方案

你可以通过两种方式解决这个问题:

  • 方式一:启用集合元素的非空校验
    修改Json序列化器的配置,开启strictNullChecks,这样在反序列化时如果集合中出现null而非元素类型为可空,会直接抛出异常,避免后续的NPE:
    val jsonSerializer = Json {
        encodeDefaults = true
        strictNullChecks = true // 启用严格null校验
    }
    
  • 方式二:显式允许集合元素为null
    如果业务上允许include列表中出现null值,将集合元素类型改为可空的String?:
    data class Ids(
        val include: List<String?>? = null,
        val exclude: List<String?>? = null
    )
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:50:14