50% 的 Java 程序员都不知道的 Jackson 高级用法!
Jackson 是目前 Java 生态中使用最广泛的 JSON 序列化/反序列化库,但绝大多数人只用到了它的最基础功能(@JsonProperty、ObjectMapper.readValue等),其实它还有非常多强大且实用的高级特性,能大幅提升代码质量、性能和可维护性。
下面列出10 个非常实用但使用率明显偏低的 Jackson 高级用法(2025–2026 视角),很多都是中高级开发者和架构师才会主动用到的。
1. @JsonAnyGetter + @JsonAnySetter(动态字段)
当 JSON 中有大量不确定字段,或者你想把 Map 字段“打平”到对象里时非常有用。
publicclassDynamicUser{privateStringname;privateMap<String,Object>extra=newLinkedHashMap<>();@JsonAnyGetterpublicMap<String,Object>getExtra(){returnextra;}@JsonAnySetterpublicvoidsetExtra(Stringkey,Objectvalue){extra.put(key,value);}}效果:
输入 JSON:{"name":"张三", "age":18, "city":"北京"}
对象中extra会自动包含age和city,而不需要提前定义所有字段。
2. @JsonUnwrapped(打平嵌套对象)
publicclassAddress{privateStringcity;privateStringstreet;}publicclassPerson{privateStringname;@JsonUnwrappedprivateAddressaddress;}序列化后:
{"name":"李四","city":"上海","street":"南京路"}非常适合把嵌套对象“展平”到顶层,常见于 DTO 与数据库实体转换。
3. @JsonInclude + @JsonInclude.Include.NON_EMPTY / NON_DEFAULT
@JsonInclude(JsonInclude.Include.NON_EMPTY)publicclassUserDTO{privateStringname;privateStringemail;// null 不输出privateIntegerage=0;// 0 不输出(NON_EMPTY 对数字无效)privateList<String>roles=Collections.emptyList();// 空集合不输出}常用变体:
NON_NULL:null 不输出(最常见)NON_EMPTY:空集合、空字符串、空 Map 不输出NON_DEFAULT:默认值不输出(boolean false、int 0 等)
4. @JsonProperty.Access(读写控制)
publicclassUser{@JsonProperty(access=JsonProperty.Access.READ_ONLY)privateLongid;// 只读,序列化有,反序列化忽略@JsonProperty(access=JsonProperty.Access.WRITE_ONLY)privateStringpassword;// 只写,反序列化有,序列化忽略@JsonProperty(access=JsonProperty.Access.AUTO)// 默认privateStringusername;}常用于:隐藏敏感字段、保护 id 不被前端修改等。
5. @JsonNaming(统一命名策略)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)publicclassUserInfo{privateStringfirstName;privateStringlastLoginTime;}输出:
{"first_name":"张","last_login_time":"2025-12-01"}支持的策略:
SnakeCaseStrategy(snake_case)KebabCaseStrategy(kebab-case)UpperCamelCaseStrategy(UpperCamelCase)LowerCaseStrategy(全小写)
6. @JsonView(视图控制,按需返回字段)
publicclassViews{publicstaticclassPublic{}publicstaticclassInternalextendsPublic{}}publicclassUser{@JsonView(Views.Public.class)privateStringusername;@JsonView(Views.Internal.class)privateStringpassword;@JsonView(Views.Internal.class)privateStringphone;}使用:
ObjectMappermapper=newObjectMapper();mapper.writerWithView(Views.Public.class).writeValueAsString(user);// 只输出 username非常适合不同接口返回不同字段集的场景(用户列表 vs 用户详情)。
7. @JsonFormat(自定义日期格式)
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")privateLocalDateTimecreateTime;支持的类型:Date、LocalDate、LocalDateTime、Instant、ZonedDateTime 等。
8. @JsonRootName(根节点名称)
@JsonRootName("response")publicclassApiResult<T>{privateintcode;privateStringmsg;privateTdata;}序列化后:
{"response":{"code":200,"msg":"success","data":{...}}}常用于统一响应结构。
9. Mix-in Annotations(不侵入实体类)
当你不能修改第三方类或想把注解放在 DTO 而不是实体时使用:
// Mix-in 类publicabstractclassUserMixIn{@JsonIgnorepublicabstractStringgetPassword();}// 配置ObjectMappermapper=newObjectMapper();mapper.addMixIn(User.class,UserMixIn.class);效果:User 类本身不加任何注解,但序列化时 password 被忽略。
10. 自定义 Deserializer / Serializer(终极武器)
publicclassMoneyDeserializerextendsJsonDeserializer<BigDecimal>{@OverridepublicBigDecimaldeserialize(JsonParserp,DeserializationContextctxt)throwsIOException{Stringtext=p.getText();// 支持 "123.45", "¥123.45", "123,45" 等returnnewBigDecimal(text.replaceAll("[¥,]",""));}}@JsonDeserialize(using=MoneyDeserializer.class)privateBigDecimalamount;快速总结:你最应该立刻掌握的 5 个
@JsonAnyGetter+@JsonAnySetter—— 处理动态字段@JsonUnwrapped—— 打平嵌套对象@JsonView—— 接口返回字段控制- Mix-in Annotations —— 不侵入第三方类
- 自定义 Deserializer —— 处理非标准格式(金额、枚举、日期等)
这些特性一旦熟练使用,能让你的 JSON 处理代码更优雅、更安全、维护成本更低。
你项目里现在用 Jackson 遇到过哪些最痛苦的场景?可以告诉我,我帮你针对性给出最优解法。