有道无术,术尚可求,有术无道,止于术。
本系列 Jackson 版本 2.17.0
源码地址:https://gitee.com/pearl-organization/study-jaskson-demo
注解大全
🙈🙈🙈紧接上篇,接下来我们介绍jackson-databind模块提供的所有注解,到这里注解大全篇就结束了。🙈🙈🙈
2.35 @JsonSerialize
@JsonSerialize用于指定序列化器,相比于全局配置,可以针对特定的字段或类,提供了更细粒度的控制,
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonSerialize {
// 指定序列化器
Class<? extends JsonSerializer> using() default JsonSerializer.None.class;
// 指定集合元素、Map键值对、数组元素序列化器
Class<? extends JsonSerializer> contentUsing() default JsonSerializer.None.class;
// 指定Map键序列化器
Class<? extends JsonSerializer> keyUsing() default JsonSerializer.None.class;
// 指定Null序列化器
Class<? extends JsonSerializer> nullsUsing() default JsonSerializer.None.class;
// 声明超类
Class<?> as() default Void.class;
// 将{@link java.util.Map}的键序列化为的具体类型
Class<?> keyAs() default Void.class;
// 将集合元素、Map键值对、数组元素序列化为的具体类型
Class<?> contentAs() default Void.class;
// 所使用的类型检测是动态的还是静态的:即,无论使用实际的运行时类型(动态),还是仅使用声明的类型(静态)
Typing typing() default JsonSerialize.Typing.DEFAULT_TYPING;
// 要使用哪个辅助对象将类型转换为某些内容
Class<? extends Converter> converter() default Converter.None.class;
// *类似于{@link#converter},但用于集合的值(List, arrays, Maps)
Class<? extends Converter> contentConverter() default Converter.None.class;
@JsonSerialize中的using是最常用的,指定JsonSerializer类型的序列化器,可以自定义,也可以使用Jackson提供的序列化器:
例如之前我们在序列化LocalDateTime 时,就指定了LocalDateTimeSerializer:
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime birthdayLocalDateTime;
2.36 @JsonDeserialize
@JsonDeserialize和@JsonSerialize用法一致,用于反序列化:
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonDeserialize {
Class<? extends JsonDeserializer> using() default JsonDeserializer.None.class;
Class<? extends JsonDeserializer> contentUsing() default JsonDeserializer.None.class;
Class<? extends KeyDeserializer> keyUsing() default KeyDeserializer.None.class;
Class<?> builder() default Void.class;
Class<? extends Converter> converter() default Converter.None.class;
Class<? extends Converter> contentConverter() default Converter.None.class;
Class<?> as() default Void.class;
Class<?> keyAs() default Void.class;
Class<?> contentAs() default Void.class;
}
2.37 @EnumNaming
EnumNamingStrategy接口用于在反序列化时,如何将枚举的字符串表示形式转换为用于映射的外部属性名称,@EnumNaming则用于指定使用哪个EnumNamingStrategy接口的实现类。
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonNaming {
Class<? extends PropertyNamingStrategy> value() default PropertyNamingStrategy.class;
}
2.38 @JsonNaming
@JsonNaming和@EnumNaming类似,用于指定PropertyNamingStrategy。
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonNaming {
Class<? extends PropertyNamingStrategy> value() default PropertyNamingStrategy.class;
}
PropertyNamingStrategy用于声明属性名称生成策略,Jackson提供了很多默认策略:
示例,序列化时将所有属性名称转为首字母大写:
@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
public class JsonNamingVO {
private Long id;
private String name;
// 省略........
}
执行序列化:
JsonNamingVO jsonNamingVO=new JsonNamingVO();
jsonNamingVO.setId(1455455612333L);
jsonNamingVO.setName("测试");
String jsonStrByJsonNamingVO = objectMapper.writeValueAsString(jsonNamingVO);
System.out.println(jsonStrByJsonNamingVO);
输出结果如下:
{"Id":1455455612333,"Name":"测试"}
2.39 @JacksonStdImpl
@JacksonStdImpl作用于序列化器(JsonSerializer)、反序列化器(JsonDeserializer),标识当前是标准的Jackson实现的。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JacksonStdImpl {
}
Jackson中很多负责序列化反序列化的类都标识了该注解:
2.40 @JsonAppend
@JsonAppend用于在序列化时添加虚拟属性(原本不属于对象中的属性)。
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonAppend {
// 虚拟属性名称
Attr[] attrs() default {};
// 虚拟值生成器
Prop[] props() default {};
boolean prepend() default false;
// 省略........
}
首先需要实现一个自定义的虚拟属性写类:
public class AddressVirtualBeanPropertyWriter extends VirtualBeanPropertyWriter {
public AddressVirtualBeanPropertyWriter() {
}
private AddressVirtualBeanPropertyWriter(BeanPropertyDefinition propDef,
Annotations contextAnnotations, JavaType declaredType) {
super(propDef, contextAnnotations, declaredType);
}
@Override
protected Object value(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws Exception {
// 返回虚拟属性对应的值
return "阿里巴巴";
}
@Override
public VirtualBeanPropertyWriter withConfig(MapperConfig<?> mapperConfig, AnnotatedClass annotatedClass, BeanPropertyDefinition beanPropertyDefinition, JavaType javaType) {
return new AddressVirtualBeanPropertyWriter(beanPropertyDefinition, null, javaType);
}
}
当前类中只有id、name属性:
@JsonAppend(props = @JsonAppend.Prop(name = "address", value = AddressVirtualBeanPropertyWriter.class))
public class JsonAppendVO {
private Long id;
private String name;
// 省略........
}
执行序列化:
JsonAppendVO jsonAppendVO=new JsonAppendVO();
jsonAppendVO.setId(1455455612333L);
jsonAppendVO.setName("测试");
String jsonStrByjsonAppendVO = objectMapper.writeValueAsString(jsonAppendVO);
System.out.println(jsonStrByjsonAppendVO);
输出结果如下:
{"id":1455455612333,"name":"测试","address":"阿里巴巴"}
2.41 @JsonPOJOBuilder
在设计模式里,构建者模式是一种创建型设计模式,它旨在将复杂对象的创建过程与其表示分离,以便以灵活、可扩展和可维护的方式构建对象。@JsonPOJOBuilder作用于POJO类的构建类Builder,Jackson会调用Builder.build()方法进行反序列化。
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonPOJOBuilder {
String DEFAULT_BUILD_METHOD = "build";
String DEFAULT_WITH_PREFIX = "with";
// 构建方法
String buildMethodName() default "build";
// 设置属性方法的前缀
String withPrefix() default "with";
// 省略........
}
POJO也可以提供Builder用于构建对象,例如下面有一个简单的类:
示例如下:
@JsonDeserialize(builder = Dog.Builder.class)
public class Dog {
private final String name;
private final Integer age;
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
private Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
@JsonPOJOBuilder
static class Builder {
String name;
Integer age;
Builder withName(String name) {
this.name = name;
return this;
}
Builder withAge(Integer age) {
this.age = age;
return this;
}
public Dog build() {
System.out.println("使用build构建");
return new Dog(name, age);
}
}
}
输出结果:
使用build构建
Dog{name='haha', age=2}
2.42 @JsonValueInstantiator
ValueInstantiator是Jackson中声明的用于创建值对象的简单API,@JsonValueInstantiator则是指定类使用哪个ValueInstantiator实现类。
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonValueInstantiator {
// ValueInstantiator实现类
Class<? extends ValueInstantiator> value();
}
示例,实现了一个ValueInstantiator,并指定了一个默认对象:
@JsonValueInstantiator(MyValueInstantiator.class)
public class ValueInstantiatorVO {
protected final String a;
protected final int b;
public ValueInstantiatorVO(String a, int b) {
this.a = a;
this.b = b;
}
@Override
public String toString() {
return "ValueInstantiatorVO{" +
"a='" + a + '\'' +
", b=" + b +
'}';
}
}
public class MyValueInstantiator extends ValueInstantiator.Base {
public MyValueInstantiator() {
super(Object.class);
}
@Override
public String getValueTypeDesc() {
return ValueInstantiatorVO.class.getName();
}
@Override
public boolean canCreateUsingDefault() { return true; }
@Override
public ValueInstantiatorVO createUsingDefault(DeserializationContext ctxt) {
return new ValueInstantiatorVO("哈哈", 3);
}
}
执行反序列化:
String strByValueInstantiatorVO = "{}";
ValueInstantiatorVO valueInstantiatorVO =objectMapper.readValue(strByValueInstantiatorVO, ValueInstantiatorVO.class);
System.out.println(valueInstantiatorVO);
输出结果:
ValueInstantiatorVO{a='哈哈', b=3}
2.43 @JsonTypeResolver
@JsonTypeResolver用于指定TypeResolverBuilder(类型解析器构建者),可以在序列化时显示属性的类型。
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonTypeResolver {
Class<? extends TypeResolverBuilder<?>> value();
}
示例如下:
public class Data {
private Long key;
@JsonCreator
Data(@JsonProperty("key") Long key) {
this.key = key;
}
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
@JsonTypeResolver(MyTypeResolverBuilder.class)
public long key() {
return key;
}
static class MyTypeResolverBuilder extends StdTypeResolverBuilder {
// 允许显示类型
@Override
protected boolean allowPrimitiveTypes(MapperConfig<?> config,
JavaType baseType) {
return true;
}
}
}
执行序列化:
Data data = new Data(1L);
Map<String, Object> mapData = new HashMap<>();
mapData.put("longInMap", 2L);
mapData.put("longAsField", data);
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
String strByJsonTypeResolver = objectMapper.writeValueAsString(mapData);
System.out.println(strByJsonTypeResolver);
输出结果:
{
"longInMap" : 2,
"longAsField" : {
"key" : [ "java.lang.Long", 1 ]
}
}
2.44 @JsonTypeIdResolver
@JsonTypeIdResolver(自定义如何生成和解析类型信息)通常需要配合@JsonTypeInfo(指定序列化时包含的类型信息)注解一起使用,用于解决在序列化和反序列化过程中可能出现的类型识别问题。
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonTypeIdResolver {
Class<? extends TypeIdResolver> value();
}
这里贴一个官方示例:
@JsonTypeInfo(use = JsonTypeInfo.Id.CUSTOM, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeIdResolver(CustomBean.CustomResolver.class)
public abstract class CustomBean {
static class CustomBeanImpl extends CustomBean {
public int x;
public CustomBeanImpl() { }
public CustomBeanImpl(int x) { this.x = x; }
}
static class CustomResolver extends TestCustomResolverBase {
// yes, static: just for test purposes, not real use
static List<JavaType> initTypes;
public CustomResolver() {
super(CustomBean.class, CustomBeanImpl.class);
}
@Override
public void init(JavaType baseType) {
if (initTypes != null) {
initTypes.add(baseType);
}
}
}
static class TestCustomResolverBase extends TypeIdResolverBase {
protected final Class<?> superType;
protected final Class<?> subType;
public TestCustomResolverBase(Class<?> baseType, Class<?> implType) {
superType = baseType;
subType = implType;
}
@Override
public JsonTypeInfo.Id getMechanism() {
return JsonTypeInfo.Id.CUSTOM;
}
@Override
public String idFromValue(Object value) {
if (superType.isAssignableFrom(value.getClass())) {
return "*";
}
return "unknown";
}
@Override
public String idFromValueAndType(Object value, Class<?> type) {
return idFromValue(value);
}
@Override
public void init(JavaType baseType) {
}
@Override
public JavaType typeFromId(DatabindContext context, String id) {
if ("*".equals(id)) {
return TypeFactory.defaultInstance().constructType(subType);
}
return null;
}
@Override
public String idFromBaseType() {
return "xxx";
}
}
}
执行序列化和反序列化:
List<JavaType> types = new ArrayList<JavaType>();
CustomBean.CustomResolver.initTypes = types;
String jsonByTypeIdResolver = objectMapper.writeValueAsString(new CustomBean[] { new CustomBean.CustomBeanImpl(28) });
System.out.println(jsonByTypeIdResolver);
types = new ArrayList<JavaType>();
CustomBean.CustomResolver.initTypes = types;
CustomBean[] result = objectMapper.readValue(jsonByTypeIdResolver, CustomBean[].class);
System.out.println(result);
结果输出:
[ {
"*" : {
"x" : 28
}
} ]
[Lcom.pearl.jacksoncore.demo.databind.anno.CustomBean;@fbd1f6