有道无术,术尚可求,有术无道,止于术。
本系列Jackson 版本 2.17.0
源码地址:https://gitee.com/pearl-organization/study-jaskson-demo
文章目录
- 1. 概述
- 2. 抽象方法
- 2.1 changeProperties
- 2.2 orderProperties
- 2.3 updateBuilder
- 2.4 modifyXx
- 3. 案例演示
- 3.1 实现
- 3.2 注册
- 3.3 测试
- 4. BeanDeserializerModifier
1. 概述
Java Bean
对象的序列化过程是比较复杂的,因为它可能包含了各种类型的属性,在Jackson
中该过程是交由BeanSerializer
来负责的。同时Jackson
也提供了扩展机制,允许通过BeanSerializerModifier
在BeanSerializer
的创建过程中进行干预和修改,从而实现对序列化过程的自定义。
2. 抽象方法
BeanSerializerModifier
定义了很多抽象的钩子方法。
2.1 changeProperties
changeProperties
是最常用的方法的,目的是提供一个钩子,允许用户自定义和调整BeanSerializer
序列化过程中使用的属性集合。通过修改这个集合,可以控制哪些属性应该被序列化,哪些应该被忽略,或者替换为其他属性等。
/*** 自定义和调整 BeanSerializer 序列化过程中使用的属性集合** @param config 序列化配置* @param beanDesc Bean 对象信息* @param beanProperties 属性集合* @return 属性集合*/public List<BeanPropertyWriter> changeProperties(SerializationConfig config,BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {return beanProperties;}
2.2 orderProperties
orderProperties
方法看名字就很好理解,允许自定义和调整序列化过程中属性的顺序。
public List<BeanPropertyWriter> orderProperties(SerializationConfig config,BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {return beanProperties;}
2.3 updateBuilder
updateBuilder
方法允许在序列化器构建的最后阶段进行自定义修改或替换。
/*** 序列化器构建的最后阶段进行自定义修改或替换** @param config 序列化配置* @param beanDesc Bean 对象信息* @param builder BeanSerializer 构建者* @return 属性集合*/public BeanSerializerBuilder updateBuilder(SerializationConfig config,BeanDescription beanDesc,BeanSerializerBuilder builder) {return builder;}
2.4 modifyXx
BeanSerializerModifier
定义了很多modify
开头的方法,在DeserializerFactory
根据类型创建了对应的序列化器之后进行调用,允许替换或增强这个反序列化器,为其添加额外的功能。
/*** 允许在 BeanSerializer 构造完成后对其进行修改或替换。** @param config 序列化配置* @param beanDesc Bean 对象信息* @param serializer 序列化器* @return 序列化器*/public JsonSerializer<?> modifySerializer(SerializationConfig config,BeanDescription beanDesc,JsonSerializer<?> serializer) {return serializer;}/*** 增强或替换 ArrayType 对应的序列化器** @param config 序列化配置* @param valueType 类型 * @param beanDesc Bean 对象信息* @param serializer 序列化器* @return 序列化器*/public JsonSerializer<?> modifyArraySerializer(SerializationConfig config,ArrayType valueType,BeanDescription beanDesc,JsonSerializer<?> serializer) {return serializer;}/*** @since 2.2*/public JsonSerializer<?> modifyCollectionSerializer(SerializationConfig config,CollectionType valueType,BeanDescription beanDesc,JsonSerializer<?> serializer) {return serializer;}/*** @since 2.2*/public JsonSerializer<?> modifyCollectionLikeSerializer(SerializationConfig config,CollectionLikeType valueType,BeanDescription beanDesc,JsonSerializer<?> serializer) {return serializer;}/*** @since 2.2*/public JsonSerializer<?> modifyMapSerializer(SerializationConfig config,MapType valueType,BeanDescription beanDesc,JsonSerializer<?> serializer) {return serializer;}/*** @since 2.2*/public JsonSerializer<?> modifyMapLikeSerializer(SerializationConfig config,MapLikeType valueType,BeanDescription beanDesc,JsonSerializer<?> serializer) {return serializer;}/*** @since 2.2*/public JsonSerializer<?> modifyEnumSerializer(SerializationConfig config,JavaType valueType,BeanDescription beanDesc,JsonSerializer<?> serializer) {return serializer;}/*** @since 2.2*/public JsonSerializer<?> modifyKeySerializer(SerializationConfig config,JavaType valueType, BeanDescription beanDesc, JsonSerializer<?> serializer) {return serializer;}
3. 案例演示
BeanSerializerModifier
的功能非常强大,几乎可以自定义很多序列化的骚操作,例如:添加额外字段、更改字段值、自定义序列化器、null
值处理、字典翻译、数据脱敏等等…
下面演示一个最简单的需求,修改某个属性序列化的值,其他高级用法后面会单独介绍。当前对象有一个password
属性,需要序列化为********
显示:
public class UserVO {Long id;String username;// 省略.............
}
3.1 实现
实现BeanSerializerModifier
,当存在password
属性时,注册一个自定义的JsonSerializer
,将值写为********
:
public class ModifyPasswordBeanSerializerModifier extends BeanSerializerModifier {/*** 自定义和调整 BeanSerializer 序列化过程中使用的属性集合** @param config 序列化配置* @param beanDesc Bean 对象信息* @param beanProperties 属性集合* @return 属性集合*/public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {System.out.println("changeProperties");// 查询是否开启某个特征boolean enabled = config.isEnabled(SerializationFeature.FAIL_ON_SELF_REFERENCES);// 获取当前Bean 的类型、真实 ClassJavaType javaType = beanDesc.getType();Class<?> rawClass = javaType.getRawClass();// 循环所有属性集合for (BeanPropertyWriter beanPropertyWriter : beanProperties) {// 属性类型JavaType type = beanPropertyWriter.getType();// 属性名称String name = beanPropertyWriter.getName();// 属性的序列化器JsonSerializer<Object> serializer = beanPropertyWriter.getSerializer();// 属性的类型列化器TypeSerializer typeSerializer = beanPropertyWriter.getTypeSerializer();// 是否有Null值序列化器boolean hasNullSerializer = beanPropertyWriter.hasNullSerializer();// 获取注解Annotation annotation = beanPropertyWriter.getAnnotation(JsonSerialize.class);// 修改字段名称if("password".equals(name)){// 当前属性Writer对象,注册自定义的序列化器beanPropertyWriter.assignSerializer(new JsonSerializer<>() {@Overridepublic void serialize(Object value, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonProcessingException {jg.writeString("********");}});}}return beanProperties;}
}
PS
:实际开发中,不推荐这么用,这个逻辑是全局的,会作用于所有Java Bean
,重点是了解基础用法,这里可以添加自定义注解(后续讲解)。
3.2 注册
可以直接在ObjectMapper
对象中注册BeanSerializerModifier
:
ObjectMapper objectMapper = new ObjectMapper();// 创建新的 SerializerFactory,并设置 BeanSerializerModifierSerializerFactory serializerFactory = objectMapper.getSerializerFactory().withSerializerModifier(new ModifyPasswordBeanSerializerModifier());// 需要重新设置进去,因为SerializerFactory 是不可变对象objectMapper.setSerializerFactory(serializerFactory);
也可以新建模块并注册:
// 使用模块注册BeanSerializerModifier:SimpleModule simpleModule=new SimpleModule("myModule");simpleModule.setSerializerModifier(new ModifyPasswordBeanSerializerModifier());objectMapper.registerModule(simpleModule);// 注册模块
3.3 测试
执行序列化操作:
UserVO userVO = new UserVO();userVO.setId(1699657986705854464L);userVO.setPassword("123456");userVO.setUsername("jack");userVO.setCreateTime(LocalDateTime.now());String userVoJson = objectMapper.writeValueAsString(userVO);System.out.println(userVoJson);
可以看到原有的password
值被修改了:
changeProperties
{"id":1699657986705854464,"username":"jack","password":"********","createTime":"2024-04-11 14:57:51"}
4. BeanDeserializerModifier
同样也提供了用于反序列化Java Bean
对象的扩展机制,也就是BeanDeserializerModifier
抽象类,在BeanDeserializer
的创建过程中进行干预和修改,从而实现对反序列化过程的自定义。和BeanSerializerModifier
用法一致,这里简单提一下,没必要赘述了。
public abstract class BeanDeserializerModifier implements Serializable {private static final long serialVersionUID = 1L;public List<BeanPropertyDefinition> updateProperties(DeserializationConfig config, BeanDescription beanDesc, List<BeanPropertyDefinition> propDefs) {return propDefs;}public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) {return builder;}public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {return deserializer;}public JsonDeserializer<?> modifyEnumDeserializer(DeserializationConfig config, JavaType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {return deserializer;}public JsonDeserializer<?> modifyReferenceDeserializer(DeserializationConfig config, ReferenceType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {return deserializer;}public JsonDeserializer<?> modifyArrayDeserializer(DeserializationConfig config, ArrayType valueType, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {return deserializer;}public JsonDeserializer<?> modifyCollectionDeserializer(DeserializationConfig config, CollectionType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {return deserializer;}public JsonDeserializer<?> modifyCollectionLikeDeserializer(DeserializationConfig config, CollectionLikeType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {return deserializer;}public JsonDeserializer<?> modifyMapDeserializer(DeserializationConfig config, MapType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {return deserializer;}public JsonDeserializer<?> modifyMapLikeDeserializer(DeserializationConfig config, MapLikeType type, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {return deserializer;}public KeyDeserializer modifyKeyDeserializer(DeserializationConfig config, JavaType type, KeyDeserializer deserializer) {return deserializer;}
}