今天遇到一个线上报警,用jackson将字符串转对象报错了。
很尴尬的是,业务里使用的是
try {
return mapper.get().readValue(json, cls);
} catch (Exception e) {
throw new RuntimeException(String.format("failed to read value from %s to %s", json, cls), e);
}
抛的异常,日志里看不到jacksjon报的错误原因。
没办法,只能自己写单测还原现场。
JacksonMapper.SNAKE_CASE.get().readValue("{...}", Test.class);
总算把jackson的异常打印出来了:
com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of Test: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: {...}; line: 1, column: 14] (through reference chain: Test)
看了一下报错的类,有声明构造函数呀:
public class Test {
public Test(A a, B b) {
}
}
百思不得其解,网上google了一下。
原来Jackson默认会去调用无参数的构造函数,如果自定义了带参数构造函数,Object自带的无参数构造函数就没有了。而且就算提供了带参数构造函数,jackson也无法无歧义地调用带参数构造函数,因为调用参数的顺序无法确定。
解决方法,显式声明一下无参数构造函数就可以了。
public class Test {
public Test() {
}
public Test(A a, B b) {
}
}