在 Java 开发中,Jackson 是处理 JSON 数据的利器。它通过丰富的注解,让开发者能够轻松地控制 Java 对象与 JSON 之间的转换。无论是在 RESTful API 开发、微服务通信,还是数据持久化与配置解析中,Jackson 都扮演着重大角色。本文将系统地介绍 Jackson 的常用注解,结合示例代码,协助你全面掌握 Jackson 注解体系。

一、基础序列化控制注解
1. @JsonProperty:指定字段在 JSON 中的名称
public class User {
public int id;
@JsonProperty("full_name")
public String name;
}
序列化结果:{“id”:1,”full_name”:”Alice”}
这个注解可以协助我们自定义字段在 JSON 中的名称,避免直接使用 Java 字段名。
2. @JsonPropertyOrder:控制字段序列化顺序
@JsonPropertyOrder({"name", "id"})
public class MyBean {
public int id;
public String name;
}
输出:{“name”:”Tom”,”id”:1}
通过这个注解,我们可以指定字段在 JSON 中的顺序,使输出更加符合预期。
3. @JsonInclude:排除空值、默认值等
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
public String name; // null 时不输出
public int age; // 0 会输出(因是基本类型)
}
这个注解可以控制序列化时是否包含某些字段,例如排除空值或默认值,使 JSON 更简洁。
4. @JsonIgnore / @JsonIgnoreProperties:忽略字段或类中的某些属性
@JsonIgnoreProperties({"password"})
public class User {
public String name;
public String password; // 不输出
}
或字段级:
public class User {
public String name;
@JsonIgnore
public String password;
}
这两个注解可以用来忽略某些字段,避免敏感信息被序列化。
二、高级序列化控制注解
1. @JsonRawValue:将字段值原样输出为 JSON,而非字符串
public class RawBean {
public String name;
@JsonRawValue
public String metadata; // 值为 "{"role":"admin"}"
}
输出:{“name”:”Bob”,”metadata”:{“role”:”admin”}}
这个注解适用于需要直接嵌入 JSON 字符串的场景,避免被转义。
2. @JsonValue:将整个对象序列化为该方法的返回值(常用于枚举)
public enum Status {
ACTIVE(1, "active"), INACTIVE(0, "inactive");
private final int code;
private final String desc;
@JsonValue
public String getDesc() { return desc; }
}
序列化 Status.ACTIVE → “active”
这个注解可以用于枚举类型,将枚举对象直接序列化为某个字段的值。
3. @JsonRootName:为整个对象包裹一个根节点
@JsonRootName("user")
public class User {
public int id;
public String name;
}
输出:{“user”:{“id”:1,”name”:”John”}}
这个注解可以在 JSON 的最外层添加一个根节点,方便与某些特定的 JSON 格式对接。
4. @JsonFormat:格式化日期/时间字段
public class Event {
public String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
public Date eventTime;
}
输出:{“name”:”会议”,”eventTime”:”2025-12-08 14:30:00″}
这个注解用于格式化日期和时间字段,确保输出的日期格式符合需求。
5. @JsonNaming:统一字段命名策略(如蛇形命名)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class NamingBean {
private String userName;
}
输出:{“user_name”:”Alice”}
这个注解可以统一类中所有字段的命名策略,例如将驼峰命名转换为蛇形命名,方便与某些特定的 JSON 格式对接。
三、反序列化控制注解
1. @JsonCreator:通过构造器或静态工厂方法反序列化
public class User {
public final String name;
public final int id;
@JsonCreator
public User(@JsonProperty("name") String name,
@JsonProperty("id") int id) {
this.name = name;
this.id = id;
}
}
这个注解可以指定通过构造器或静态工厂方法来反序列化对象,适用于不可变对象的创建。
2. @JsonAlias:支持多个 JSON 字段名映射到同一 Java 字段
public class Person {
@JsonAlias({"fName", "first_name"})
public String firstName;
}
支持 {“fName”:”Tom”} 或 {“first_name”:”Tom”}
这个注解可以为字段指定多个别名,使 JSON 数据在字段名不一致时也能正确反序列化。
3. @JsonAnySetter:将 JSON 中未知字段存入 Map
public class ExtendableBean {
public String name;
private Map<String, String> props = new HashMap<>();
@JsonAnySetter
public void add(String key, String value) {
props.put(key, value);
}
}
这个注解可以将 JSON 中未知的字段存储到一个 Map 中,方便处理动态字段。
4. @JacksonInject:从外部注入值,而非从 JSON 读取
public class InjectBean {
@JacksonInject("tenantId")
public String tenantId;
public String name;
}
// 使用
InjectableValues values = new InjectableValues.Std().addValue("tenantId", "T1001");
User u = mapper.reader(values).forType(InjectBean.class).readValue(json);
这个注解可以将外部值注入到对象中,而不是从 JSON 数据中读取,适用于某些需要外部配置的场景。
5. @JsonDeserialize:指定自定义反序列化器(与 @JsonSerialize 对应)
public class Event {
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}
这个注解可以指定一个自定义的反序列化器,用于处理复杂的字段类型。
四、多态类型处理
1. @JsonTypeInfo + @JsonSubTypes:支持多态反序列化
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal {
public String name;
}
public class Dog extends Animal {
public double barkVolume;
}
输入:{“type”:”dog”,”name”:”Lacy”,”barkVolume”:8.5} → 自动创建 Dog 实例
这两个注解可以用于处理多态类型,使 Jackson 能够根据 JSON 中的类型标识正确地反序列化为对应的子类。
2. @JsonTypeName:为子类指定逻辑类型名
@JsonTypeName("canine")
public class Dog extends Animal { ... }
这个注解可以为子类指定一个逻辑类型名,方便在多态反序列化时识别。
3. @JsonTypeId:将字段值作为类型 ID 使用
public class TypeIdBean {
public int id;
@JsonTypeId
public String typeName;
}
序列化结果:[“Admin”, {“id”:1}]
这个注解可以将某个字段的值用作类型 ID,用于多态类型标识。
4. @JsonTypeIdResolver:自定义类型 ID 与 Java 类的映射逻辑
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type")
@JsonTypeIdResolver(MyIdResolver.class)
public abstract class Animal { ... }
配合 TypeIdResolverBase 实现灵活映射(如 bean1 → FirstBean.class)。
这个注解可以自定义类型 ID 与 Java 类的映射逻辑,适用于复杂的多态类型场景。
五、循环引用与对象标识
1. @JsonIdentityInfo:通过对象 ID 解决循环引用
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class User {
public int id;
public List<Order> orders;
}
public class Order {
public int id;
public User user; // 第二次出现时只输出 id
}
这个注解可以为对象生成一个唯一的 ID,并在序列化时使用这个 ID 来解决循环引用问题。
2. @JsonIdentityReference(alwaysAsId = true):强制始终输出 ID,而非完整对象
@JsonIdentityInfo(property = "id", generator = ObjectIdGenerators.PropertyGenerator.class)
@JsonIdentityReference(alwaysAsId = true)
public class UserRef {
public int id;
public String name;
}
序列化结果:”1″(直接输出 ID 字符串)
这个注解可以强制始终输出对象的 ID,而不是完整的对象,适用于某些需要简化输出的场景。
3. @JsonManagedReference / @JsonBackReference:用于父子双向关联(如订单-用户)
public class Order {
public int id;
@JsonManagedReference
public User user;
}
public class User {
public String name;
@JsonBackReference
public List<Order> orders;
}
这个注解组合可以用于处理父子双向关联,避免在序列化时出现循环引用。
六、动态控制与扩展:高级场景下的灵活映射
Jackson 不仅支持静态注解控制 JSON 行为,还提供了一系列动态、运行时可控的机制,用于应对权限隔离、字段裁剪、虚拟属性注入、构建器反序列化等复杂工程需求。本节将详细介绍 @JsonView、@JsonFilter、@JsonAppend、@JsonPOJOBuilder 和 @JsonPropertyDescription 的完整用法与适用场景。
1. @JsonView:基于视图的字段可见性控制
核心作用
@JsonView 允许你定义多个“视图”,并在序列化/反序列化时按需激活某一视图,仅处理该视图所包含的字段。这是实现“同一实体类、多种输出形态”的优雅方案。
示例代码
// 定义视图层级
class Views {
public static class Public {} // 基础视图
public static class Internal extends Public {} // 内部视图,包含 Public 所有字段
}
// 在实体类中标注字段
public class User {
@JsonView(Views.Public.class)
public Long id;
@JsonView(Views.Public.class)
public String username;
@JsonView(Views.Internal.class)
public String email;
@JsonView(Views.Internal.class)
public String phoneNumber;
}
序列化时,根据不同的视图需求,可以输出不同的字段组合:
// 公开视图:仅返回基础信息
String publicJson = mapper
.writerWithView(Views.Public.class)
.writeValueAsString(user);
// 输出:{"id":1001,"username":"alice"}
// 内部视图:返回完整信息
String internalJson = mapper
.writerWithView(Views.Internal.class)
.writeValueAsString(user);
// 输出:{"id":1001,"username":"alice","email":"alice@company.com","phoneNumber":"138****5678"}
适用场景
- 对外 API vs 内部管理后台
- 用户基本信息 vs 敏感信息(如手机号、邮箱)
- 减少移动端流量(仅返回必要字段)
2. @JsonFilter:运行时动态字段过滤
核心作用
相比 @JsonView 的“编译期静态定义”,@JsonFilter 支持在运行时动态决定保留或排除哪些字段,灵活性更高。
示例代码
@JsonFilter("userFilter") // 绑定过滤器名称
public class User {
public String name;
public String email;
public String password;
public String department;
}
// 白名单:仅保留 name 和 email(适用于公开接口)
SimpleBeanPropertyFilter allowList = SimpleBeanPropertyFilter
.filterOutAllExcept("name", "email");
// 黑名单:排除 password(适用于内部接口脱敏)
SimpleBeanPropertyFilter denyList = SimpleBeanPropertyFilter
.serializeAllExcept("password");
FilterProvider filters = new SimpleFilterProvider()
.addFilter("userFilter", allowList); // 或 denyList
String json = mapper.writer(filters).writeValueAsString(user);
适用场景
- 动态数据脱敏:根据用户角色决定是否返回手机号、身份证号等
- 多租户系统:不同租户可见字段不同
- API 版本兼容:v1 返回 a,b;v2 返回 a,b,c
3. @JsonAppend:无侵入式注入虚拟属性
核心作用
在不修改原始类的前提下,向 JSON 输出中注入额外的“虚拟字段”,如 version、traceId、apiSource 等元数据。
示例代码
@JsonAppend(attrs = {
@JsonAppend.Attr(value = "version", type = String.class),
@JsonAppend.Attr(value = "traceId", type = String.class),
@JsonAppend.Attr(value = "timestamp", type = Long.class)
})
public class Product {
public String id;
public String name;
public double price;
}
Product p = new Product();
p.id = "P1001";
p.name = "智能手表";
p.price = 1999.0;
String json = mapper.writer()
.withAttribute("version", "v2.1")
.withAttribute("traceId", UUID.randomUUID().toString())
.withAttribute("timestamp", System.currentTimeMillis())
.writeValueAsString(p);
输出结果:
{
"id": "P1001",
"name": "智能手表",
"price": 1999.0,
"version": "v2.1",
"traceId": "a1b2c3d4-...",
"timestamp": 1700000000000
}
适用场景
- API 版本标识(便于前端兼容)
- 链路追踪(注入 traceId)
- 审计字段(如 lastModifiedBy)
- 多端标识(如 source: “mobile”)
4. @JsonPOJOBuilder:支持非标准 Builder 模式的反序列化
核心作用
当使用 Builder 模式构造不可变对象时,若 Builder 方法不符合 Jackson 默认命名规则(如 withName 或 setName),需用此注解显式配置。
示例代码
// 主类:指定使用 Builder 反序列化
@JsonDeserialize(builder = User.Builder.class)
public class User {
private final String name;
private final int age;
private User(String name, int age) {
this.name = name;
this.age = age;
}
public static class Builder {
private String nameValue;
private int ageValue;
// 非标准前缀:constructXxx
public Builder constructName(String name) {
this.nameValue = name;
return this;
}
public Builder constructAge(int age) {
this.ageValue = age;
return this;
}
public User build() {
return new User(nameValue, ageValue);
}
}
}
// 配置 Builder 的方法命名规则
@JsonPOJOBuilder(
withPrefix = "construct", // setter 方法前缀
buildMethodName = "build" // 构建方法名
)
public static class Builder { /* 同上 */ }
// 反序列化
String json = "{"name":"Tom", "age":30}";
User user = new ObjectMapper().readValue(json, User.class);
// 成功创建 User 对象
适用场景
- 不可变对象(Immutable POJO)
- 领域驱动设计(DDD)中的聚合根
- 与 Record Builder 结合
5. @JsonPropertyDescription:为 JSON Schema 生成人类可读描述
核心作用
在生成 JSON Schema(如用于 OpenAPI/Swagger、JSON 校验)时,为字段添加语义化描述,提升接口文档可读性。
示例代码
public class User {
@JsonPropertyDescription("用户全局唯一标识,由系统分配")
public String id;
@JsonPropertyDescription("登录用户名,3-20位字母或数字")
public String username;
@JsonPropertyDescription("用户电子邮箱,用于接收通知")
public String email;
}
生成的 JSON Schema 片段:
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "用户全局唯一标识,由系统分配"
},
"username": {
"type": "string",
"description": "登录用户名,3-20位字母或数字"
},
"email": {
"type": "string",
"description": "用户电子邮箱,用于接收通知"
}
}
}
适用场景
- 自动生成接口文档
- 前端/后端契约校验
- 数据治理与元数据管理
七、其他高级特性
1. 自定义组合注解
通过 @JacksonAnnotationsInside 定义复用注解。
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonInclude(Include.NON_NULL)
@JsonPropertyOrder({"name", "id"})
public @interface PublicAPI {}
@PublicAPI
public class User { ... }
2. MixIn 注解
不修改原类,动态添加注解行为。
// 原始类无法修改
public class ThirdPartyUser { public String password; }
// MixIn 类
abstract class UserMixIn {
@JsonIgnore
public String password;
}
// 注册
mapper.addMixIn(ThirdPartyUser.class, UserMixIn.class);
3. 禁用所有注解
全局关闭注解功能(调试或安全场景)。
ObjectMapper mapper = new ObjectMapper();
mapper.disable(MapperFeature.USE_ANNOTATIONS);
八、总结:Jackson 注解全景图
|
功能类别 |
核心注解 |
|
字段映射 |
@JsonProperty, @JsonGetter, @JsonSetter |
|
命名与顺序 |
@JsonNaming, @JsonPropertyOrder |
|
日期格式 |
@JsonFormat |
|
空值/默认值控制 |
@JsonInclude, @JsonIncludeProperties |
|
忽略字段 |
@JsonIgnore, @JsonIgnoreProperties, @JsonIgnoreType |
|
循环引用 |
@JsonIdentityInfo, @JsonIdentityReference, @JsonManagedReference |
|
多态类型 |
@JsonTypeInfo, @JsonSubTypes, @JsonTypeName, @JsonTypeId, @JsonTypeIdResolver |
|
动态控制 |
@JsonView, @JsonFilter |
|
扩展与注入 |
@JsonAppend, @JsonAnyGetter, @JsonAnySetter, @JacksonInject |
|
构建器支持 |
@JsonCreator, @JsonPOJOBuilder |
|
自定义序列化 |
@JsonSerialize, @JsonDeserialize, @JsonValue |
|
工具与元信息 |
@JsonPropertyDescription, @JsonRootName, @JsonAutoDetect |
Jackson 注解体系强劲而灵活,几乎可以应对所有 JSON 处理场景。合理组合使用这些注解,可大幅提升系统健壮性、安全性与可维护性。提议在项目中:
- 全局统一命名策略、日期格式
- 用 @JsonView 或 @JsonFilter 实现权限控制
- 用 @JsonIdentityInfo 安全处理循环引用
- 用 @JsonAppend 无侵入注入元数据

致谢
感谢您阅读到这里!如果您觉得这篇文章对您有所协助或启发,希望您能给我一个小小的鼓励:
- 点赞:您的点赞是我继续创作的动力,让我知道这篇文章对您有价值!
- 关注:关注我,您将获得更多精彩内容和最新更新,让我们一起探索更多知识!
- 收藏:方便您日后回顾,也可以随时找到这篇文章,再次阅读或参考。
- 转发:如果您认为这篇文章对您的朋友或同行也有协助,欢迎转发分享,让更多人受益!
您的每一个支持都是我不断进步的动力,超级感谢您的陪伴和支持!如果您有任何疑问或想法,也欢迎在评论区留言,我们一起交流!






廉颇老矣
这原文是,凭谁问,廉颇老矣,尚能饭否。我想说的是,如果是别人问,那就是借坡下驴,说吃不下了。但是自己问自己,那就应该答还能吃下一头驴。明心见性,知行合一 与君共勉
收藏了,感谢分享
感谢[祝福][祝福][祝福]