使用writeValueAsString序列化对象后,Jackson反序列化失败

9
使用 com.fasterxml.jackson.databind.ObjectMapper 类(com.fasterxml.jackson.core:jackson-databind:2.9.5),我正在尝试反序列化以下类的对象:
class MyClass {

    String name;

    MyClass(String name) {
        this.name = name;
    }
}

我现在执行的代码如下:

我现在执行的代码如下:

    MyClass myClass = new MyClass("test");
    objectMapper.registerModule(new ParameterNamesModule())
        .registerModule(new Jdk8Module())
        .registerModule(new JavaTimeModule())
        .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
        .setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

    String text = objectMapper.writeValueAsString(myClass);
    objectMapper.readValue(text, MyClass.class);

在最后一行抛出异常的情况下失败:

com.fasterxml.jackson.databind.exc.MismatchedInputException: 无法构造com.pckge.MyClass的实例(尽管至少存在一个创建者):无法从对象值反序列化(没有委托或基于属性的创建者) 在[源:(String)“ {”name“:“test”}”;行:1,列:2]

我的目标是配置对象映射器以成功反序列化对象,而不使用MyClass构造函数上的JsonCreator或JsonProperties等注释:

  • 这可行吗?
  • 我缺少哪些配置?

非常感谢!

编辑1:@Dean的回复解决了问题。但我想避免默认构造函数。

5个回答

26

如果没有默认构造函数,解决这个问题的正确方法是在类构造函数上添加@JsonCreator和@JsonProperty注释。

class MyClass {

    String name;

    @JsonCreator
    MyClass(@JsonProperty("name") String name) {
        this.name = name;
    }
    ...
}

这应该是被接受的答案。它比添加NoArg构造函数和公共setter要好得多 - name字段应该是final! - scibuff

12

Jackson使用Getter和Setter方法来设置值。因此,您需要修改您的类:

class MyClass {

    String name;

    MyClass(String name) {
      this.name = name;
   }

   MyClass(){}

   public void setName(String name) {
     this.name = name;
   }

  public String getName(String name) {
     return this.name;
  }
}

2
这解决了问题。如果我们不想创建默认构造函数怎么办? - pafede2
4
不幸的是,这需要使用默认构造函数。 - Dean

7

如果您正在使用Lombok,请移除类上的@Builder注释,这是我的问题。


2
我的问题是从类中删除@Builder(Lombok)注释,然后添加@AllArgsConstructor和@NoArgsConstructor注释,它起作用了。

它对我也起作用了,但我不明白为什么,请你能解释一下吗? - yernazarov

0
我移除了@Builder(Lombok),它可以正常工作,因为@Builder会创建一个私有构造函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接