在Kotlin中,Jackson数据类的反序列化错误

不确定如何最好地解释这个问题,所以我讽刺了java和kotlin相同的代码来更好的演示。

当我读取JSON时,即使参数甚至不是json的一部分,数据bean默认值是缺少字段的值,但它似乎强制数据bean值为NULL。 在Java中它正常工作,从来没有试图取消从未提供开始的值。 在Kotlin,它似乎打破了,因为它试图取消一个不可空的字段。

在Kotlin

data class Pojo(val name: String, val age: Int, val list: List<String> = emptyList(), val ts: Date = Date()) private val mapper: ObjectMapper = ObjectMapper().registerModule(KotlinModule()) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) fun main(args: Array<String>) { mapper.readValue("""{"name": "John Doe", "list": ["yellow", "green"], "age": 42}""", Pojo::class.java) } 

哪个抛出异常

 java.lang.IllegalArgumentException: Parameter specified as non-null is null: method Pojo.<init>, parameter ts 

在Java(一切工作正常)

 public class Transform { private static ObjectMapper mapper = new ObjectMapper() .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); public static class Pojo { private String name; private int age; private List<String> list; private Date ts = new Date(); <getters and setters for all> } public static void main(String[] args) throws IOException { String json = "{\"name\": \"John Doe\", \"list\": [\"yellow\", \"green\"], \"age\": 42}"; Pojo p = mapper.readValue(json, Pojo.class); System.out.printf("Bean: name=%s, age=%s, list=%s, ts=%s\n", p.name, p.age, p.list, p.ts); } } 

即使我把它作为一个类而不是kotlin中的一个数据类,它仍然以相同的方式出错。

我的问题是,我怎样才能让我的POJO的杰克逊反序列化在Kotlin工作。 预期的行为是,如果一个null /不正确的值被传递给不允许null的地方,它应该“中断”。 但是在上面的场景中,根本没有任何尝试将ts字段更改为null,它应该像使用java一样使用默认值。

我认为似乎工作的唯一的东西是根本不使用数据bean的概念,并写我的豆

 class Pojo(val name: String, val age: Int) { var list: List<String> = emptyList() var ts: Date = Date() } 

但是,然后我的.equals不起作用,它允许下游的其他人操纵列表和ts属性的内容,当我希望他们是只读的。

随着jackson-kotlin-module2.8.0发布,它:

现在支持在构造函数和创建者方法中使用默认值

以下示例描述了该功能:

 data class Question(val title: String = "Is programming hard?", val answer: String) val q = mapper.readValue<Question>("""{"answer": "Sure it can be"}""") println(q) //-> Question(title=Is programming hard?, answer=Sure it can be) 

我认为你的传入属性是空的,所以你需要放置? 之后jsonProperty可能是空的(在你的情况下,这是你的日期字段)。 您也可以使用原始字符串数据类型为您的测试与三重引号"""\unescaped string"""所以它应该是这样val ts: Date? 在你的数据类中。 而且你不必重新声明类型。 所以最终的答案是: data class Pojo(val name: String, val age: Int, val list: List<String>, val ts: Date?)