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

时间:2016-07-17 22:36:07

标签: json jackson kotlin

不确定如何最好地解释这个问题,所以我提出了与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属性的内容。

2 个答案:

答案 0 :(得分:12)

2.8.0发布jackson-kotlin-module

  

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

以下示例描述了该功能:

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?)