Jackson在Kotlin中:如何修复错误"No Creators, like default construct, exist"

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么你的Kotlin代码会突然“搞垮”Jackson?



你是否曾经在Kotlin中编写了一个漂亮、简洁的data class,添加了几个字段,然后通过Jackson进行JSON反序列化——却突然遇到一个又长又吓人的错误?熟悉吗?如果是,那你并不孤单。"No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator" 这个错误是Stack Overflow上从Java转向Kotlin的开发者中最常见的查询之一(数千次浏览!)。



在本文中,我们不仅会翻译错误文本。我们将“用显微镜”剖析它:它为什么会出现,如何复现它,最重要的是——如何一劳永逸地摆脱它。你不仅会得到理论,还会获得现成的、经过验证的Kotlin代码解决方案。开始吧!



这个错误到底是什么意思?简单来说



让我们想象一下,Jackson就像一个“建筑工人”,需要用JSON的砖块来组装你类的对象。要建造房子,建筑工人需要一个清晰的蓝图(构造函数)或者至少有一套现成的墙壁(字段)。



"No Creators, like default construct, exist" 这个错误字面意思是:“尊敬的Jackson,我无法创建这个类的对象,因为它没有默认构造函数(无参数),而且我不知道如何从传入的JSON字段中组装它!”



在Java中,一切都很简单:如果你没有编写任何构造函数,编译器会友好地创建一个默认的无参构造函数。Jackson看到它并愉快地使用它。而在Kotlin中,如果你在构造函数中定义了带有参数的data class,无参构造函数不会自动创建。而Jackson默认情况下寻找的正是它。



复现问题:会抛出错误的代码



让我们编写一个简单的示例,保证会引发这个错误。假设我们有一个用户类:



import com.fasterxml.jackson.databind.ObjectMapperimport com.fasterxml.jackson.module.kotlin.readValueimport com.fasterxml.jackson.module.kotlin.jacksonObjectMapper

// 注意:这段代码会引发错误!data class User(val name: String, val age: Int)

fun main() { val mapper: ObjectMapper = jacksonObjectMapper() val json = """{"name": "阿列克谢", "age": 30}"""

// 尝试将JSON反序列化为User对象 val user: User = mapper.readValue(json) println(user)}


运行这段代码,你会得到那个“著名”的异常:



com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `User` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (String)"{"name": "阿列克谢", "age": 30}"; line: 1, column: 2]


这就是我们的Stack Overflow“明星”!为什么会发生这种情况?因为data class User(val name: String, val age: Int) 没有无参构造函数。它的所有字段都在主构造函数中声明,并且是必需的(val)。Jackson无法创建User,因为它不知道为name和age传递什么值,并且没有setter作为提示。



修复错误的3种方法(从简单到正确)



好消息:有几种解决方案。选择取决于你希望控制过程的程度以及你认为什么样的代码是“干净的”。



方法1:最简单(但不适合Kotlin纯粹主义者)



手动添加一个无参构造函数。在Kotlin中,这可以通过为所有字段指定默认值来实现。



import com.fasterxml.jackson.databind.ObjectMapperimport com.fasterxml.jackson.module.kotlin.readValueimport com.fasterxml.jackson.module.kotlin.jacksonObjectMapper

// 是

博客

书籍推荐