不确定如何最好地解释这个问题,所以我提出了与java和kotlin相同的代码以更好地演示。
当我读取JSON时,它似乎强制数据bean值为NULL,即使该参数甚至不是json的一部分,并且数据bean默认为缺少字段的值。在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的概念并编写像我这样的bean
class Pojo(val name: String, val age: Int) {
var list: List<String> = emptyList()
var ts: Date = Date()
}
但是我的.equals不起作用,当我希望它们是只读时,它允许其他下游操作列表和ts属性的内容。
答案 0 :(得分:12)
现在支持在构造函数和创建者方法中使用默认值
以下示例描述了该功能:
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)
答案 1 :(得分:-1)
我认为你的一个传入属性是null,所以你需要在jsonProperty之后放置?
,这可能是null(在你的情况下这是你的日期字段)。您还可以使用原始字符串数据类型进行三引号"""\unescaped string"""
的测试
所以它应该是这样的
您的数据类内部val ts: Date?
。而且您不必重新声明类型。
所以最终答案是:
data class Pojo(val name: String, val age: Int, val list: List<String>, val ts: Date?)