使用 writeValueAsString 序列化对象后 Jackson 反序列化失败
Posted
技术标签:
【中文标题】使用 writeValueAsString 序列化对象后 Jackson 反序列化失败【英文标题】:Jackson deserialization fails after serializing an object using writeValueAsString 【发布时间】:2018-12-26 11:43:34 【问题描述】:使用 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
的实例(尽管至少存在一个创建者):无法从对象值反序列化(没有基于委托或基于属性的创建者) 在 [Source: (String)""name":"test"";行:1,列:2]
我的目标是配置对象映射器,以便成功反序列化对象,而无需在 MyClass 的构造函数上使用 JsonCreator 或 JsonProperties 等注释:
这可行吗? 我缺少哪种配置?非常感谢!
编辑 1:@Dean 的回复解决了这个问题。但是我也想避免使用默认构造函数。
【问题讨论】:
【参考方案1】: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】:在没有默认构造函数的情况下解决这个问题的正确方法是在类构造函数中添加 JsonCreator 和 JsonProperty 注释。
class MyClass
String name;
@JsonCreator
MyClass(@JsonProperty("name") String name)
this.name = name;
...
【讨论】:
这应该是公认的答案。这比添加 NoArg 构造函数和公共设置器要好得多 -name
字段应该是最终的!【参考方案3】:
如果您使用的是 loombok,请删除该类的 @Builder 注释,这是我的问题
【讨论】:
【参考方案4】:我的方法是从类中删除 @Builder(Lombok) 注释并添加 @AllArgsConstructor 和 @NoArgsConstructor 注释,它起作用了
【讨论】:
以上是关于使用 writeValueAsString 序列化对象后 Jackson 反序列化失败的主要内容,如果未能解决你的问题,请参考以下文章