Spring Boot JaxbContextContainer:Kotlin数据类无参构造函数缺失报错
解决JAXB反序列化Kotlin数据类时的无参构造函数错误
问题原因
JAXB(你使用的是GlassFish的JAXB实现)在反序列化XML对象时,要求目标类必须提供无参默认构造函数。而你定义的Kotlin数据类Rss因为所有属性都在主构造函数中且为非空val,Kotlin编译器只会生成带参数的构造函数,没有无参版本,因此触发IllegalAnnotationsException。
解决方案
以下是几种可行的解决方式,按推荐程度排序:
1. 使用Kotlin no-arg 编译器插件(推荐)
这个插件会自动给指定注解的类生成无参构造函数,无需修改现有数据类代码。
步骤:
- 在项目构建文件(
build.gradle.kts或build.gradle)中添加插件:// build.gradle.kts plugins { kotlin("jvm") version "你的Kotlin版本号" kotlin("plugin.noarg") version "你的Kotlin版本号" } noArg { // 给所有标注了@XmlRootElement的类自动生成无参构造 annotation("jakarta.xml.bind.annotation.XmlRootElement") // 可选:指定包范围,比如只给com.example.rss.model下的类生成 // packageNames.add("com.example.rss.model") } - 保留原数据类代码不变,插件会在编译时自动为
Rss类生成无参构造函数,JAXB就能正常反序列化了。
2. 手动给数据类添加无参构造(无插件方案)
修改Rss类的主构造函数,给属性设置默认值,让Kotlin编译器自动生成无参构造:
import jakarta.xml.bind.annotation.XmlAccessType import jakarta.xml.bind.annotation.XmlAccessorType import jakarta.xml.bind.annotation.XmlElement import jakarta.xml.bind.annotation.XmlRootElement @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) data class Rss( @field:XmlElement val channel: Channel? = null // 设为可空并赋予默认值null )
如果channel不能为null,可以考虑使用lateinit var(注意只能用于var):
@XmlRootElement @XmlAccessorType(XmlAccessType.NONE) data class Rss() { // 无参主构造 @field:XmlElement lateinit var channel: Channel }
这种方式需要注意lateinit变量必须在使用前被初始化,JAXB反序列化时会通过反射设置值,因此可以正常工作,但data类的equals/hashCode等方法逻辑会受主构造无参的影响,需按需选择。
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

