jackson 的 annotationintrospector 是控制序列化/反序列化行为的核心扩展点,需继承并重写其方法(如 hasignoremarker、findserializer)以响应自定义注解,再通过 objectmapper 注册实现动态行为。

Jackson 的 AnnotationIntrospector 是控制序列化/反序列化行为的核心扩展点之一,它负责“读取”类、字段、方法上的注解,并据此决定如何处理属性(比如是否忽略、重命名、使用何种序列化器等)。要通过自定义注解改变序列化行为,关键不是“直接在 AnnotationIntrospector 里写逻辑”,而是**继承并重写其方法,让 Jackson 在遇到你的注解时返回你期望的元数据(如 name、serializer、visibility 等)**。
定义你的自定义注解
先创建一个运行时保留的注解,比如用于动态控制字段是否序列化:
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ConditionalSerialize {
String value() default ""; // 可用于传条件表达式或 key
boolean enabled() default true;
}
这个注解本身不带逻辑,只是标记意图。真正的判断和行为由 AnnotationIntrospector 和后续的序列化器协同完成。
继承 AnnotationIntrospector 实现自定义解析逻辑
你需要继承 AnnotationIntrospector(推荐继承 SimpleAnnotationIntrospector,更轻量),并重写关键方法。最常用的是:
-
findSerializer(Annotated):为字段/属性指定自定义序列化器 -
hasIgnoreMarker(Annotated):告诉 Jackson 是否应忽略该字段(比@JsonIgnore更灵活) -
findNameForSerialization(Annotated):动态改字段名
示例:用 @ConditionalSerialize(enabled = false) 让字段跳过序列化:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
public class MyAnnotationIntrospector extends SimpleAnnotationIntrospector {
@Override
public Boolean hasIgnoreMarker(AnnotatedMember m) {
ConditionalSerialize ann = m.getAnnotation(ConditionalSerialize.class);
if (ann != null && !ann.enabled()) {
return Boolean.TRUE; // 明确告诉 Jackson 忽略它
}
return super.hasIgnoreMarker(m); // 委托给默认逻辑(如 @JsonIgnore)
}
}
注册自定义 AnnotationIntrospector 到 ObjectMapper
不能只 new 一个实例就完事,必须将其“注入”到 Jackson 的模块链中。推荐方式是通过 SimpleModule 或直接设置:
ObjectMapper mapper = new ObjectMapper(); mapper.setAnnotationIntrospector(new MyAnnotationIntrospector()); // 或更推荐:与模块结合(尤其需要配合自定义 Serializer 时) SimpleModule module = new SimpleModule(); module.setAnnotationIntrospector(new MyAnnotationIntrospector()); mapper.registerModule(module);
注意:setAnnotationIntrospector 会覆盖默认的(包括 JacksonAnnotationIntrospector),所以如果你仍需支持 @JsonProperty 等原生注解,应在自定义类中调用 super.xxx() 委托处理。
进阶:配合自定义 Serializer 实现动态行为
如果仅靠忽略不够,比如你想根据注解参数(如 value())动态决定输出值(如脱敏、格式化),那就需要:
- 在
findSerializer()中返回一个自定义JsonSerializer - 把注解信息(如
ann.value())传入 serializer 构造函数或上下文 - 在
serialize()方法里做运行时判断
例如:@ConditionalSerialize(value = "mask") → 输出星号掩码;value = "uppercase" → 转大写。
此时 AnnotationIntrospector 的作用就是“桥梁”:它从注解提取配置,交给 serializer 执行。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










