@JsonCreator
Jackson在反序列化的时候,会使用实体的默认无参构造函数来实例化一个对象,然后使用对象的setter方法来初始化属性值,如果没有定义无参构造函数会发生什么呢,我们来看下
@AllArgsConstructor
@Getter
@Setter
class Player{
String name;
int age;
}
测试代码如下
@Test
public void JsonCreatorTest() throws Exception{
CombineJacksonAnnotation.Player player = om.readValue("{\n" +
" \"name\" : \"tom\",\n" +
" \"age\" : 12" +
"}",CombineJacksonAnnotation.Player.class);
}
运行之后,会看到Jackson报错
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.ittx.cbt.report.service.jackson.CombineJacksonAnnotation$Player` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
根据提示可以看到,在反序列化对象的时候,要提供默认的无参构造函数,或是
delegate- or property-based Creator。
所以我们可以使用@JsonCreator来指定反序列化时候的构造函数,如下
@AllArgsConstructor
@Getter
@Setter
class Player{
@JsonCreator
public Player(@JsonProperty("name") String name){
this.name = name;
this.age =10;
System.out.println("test case");
}
String name;
int age;
}
再次运行测试代码,结果如下
image.png
可以看到不报错了,虽然我们在反序列化时候,实例化一个Player的时候将age初始化成了10,但是Jackson会继续的使用setter方法将其赋值为12,注意在使用@JsonCreator指定反序列化构造函数时,参数一定要使用@JsonProperty指定Json key的名称。
@JsonEnumDefaultValue
此注解比较简单,可以在反序列化枚举时指定默认的value,如下
enum Animal{
DOG,
@JsonEnumDefaultValue
CAT;
}
测试代码如下
image.png
可以看到成功的反序列化到了DOG对象,但是如果我们改下代码
image.png
可以看到当反序列化找不到对象的时候,成功的反序列化成了CAT,注意此注解要生效,记得加上
om.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
当人我们可以使用前面讲的@JsonCreator来指定反序列化的构造方法,代码如下
enum Animal{
DOG,
@JsonEnumDefaultValue
CAT;
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static Animal animalValueOf( String type){
if(type.equals("dog")){
return DOG;
}
return null;
}
}
继续运行代码
image.png
可以看到这个时候animal被反序列化成了null,个人建议使用@JsonCreator来反序列化枚举对象,这个灵活性和可控性更强。
网友评论