资讯动态

Spring Boot 如何自定义 Jackson JsonMapper 调整 JSON 序列化行为?

发布时间:2026/9/9 22:41:41 来源:尧图企业网站定制
Spring Boot 如何自定义 Jackson JsonMapper 调整 JSON 序列化行为【免费下载链接】spring-bootSpring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.项目地址: https://gitcode.com/gh_mirrors/sp/spring-boot如果你的 Spring Boot 应用使用 Jackson 3 序列化 JSON任何RestController在 Jackson 3 位于 classpath 上时默认就渲染 JSON 响应你可能需要调整自动配置的tools.jackson.databind.json.JsonMapper开启缩进输出、控制空值属性是否包含、注册自定义序列化器甚至彻底替换默认的 Mapper。Spring Boot 提供了从环境属性到 Bean 定制、再到完全替换的多个层次的控制点本文按从轻到重的顺序说明每条路径并给出文档中示例代码的写法。前提应用中存在自动配置的JsonMapper。只要 Jackson 3 在 classpath 上Spring Boot 就会自动配置tools.jackson.databind.json.JsonMapperBean它包含在spring-boot-starter-json中。注意Jackson 2 的支持已弃用仅在从 Jackson 2 迁移时保留长期项目不应依赖它Jackson 2 走spring.jackson2.*属性和Jackson2ObjectMapperBuilderCustomizer与本文的 Jackson 3 路径不同。通过 spring.jackson.* 环境属性调整序列化行为最轻量的方式是直接用环境属性配置JsonMapper。Jackson 提供了一系列 on/off feature它们在 Jackson 中由枚举定义在 Spring Boot 中映射为环境属性枚举属性取值tools.jackson.databind.cfg.DateTimeFeaturespring.jackson.datatype.datetime.feature_nametrue、falsetools.jackson.databind.cfg.EnumFeaturespring.jackson.datatype.enum.feature_nametrue、falsetools.jackson.databind.cfg.JsonNodeFeaturespring.jackson.datatype.json-node.feature_nametrue、falsecom.fasterxml.jackson.annotation.JsonInclude$Includespring.jackson.default-property-inclusionalways、non_null、non_absent、non_default、non_emptytools.jackson.databind.DeserializationFeaturespring.jackson.deserialization.feature_nametrue、falsetools.jackson.core.json.JsonReadFeaturespring.jackson.json.read.feature_nametrue、falsetools.jackson.core.json.JsonWriteFeaturespring.jackson.json.write.feature_nametrue、falsetools.jackson.databind.MapperFeaturespring.jackson.mapper.feature_nametrue、falsetools.jackson.databind.SerializationFeaturespring.jackson.serialization.feature_nametrue、false例如要开启 pretty print设置spring.jackson.serialization.indent_outputtrue。这里用到了宽松绑定relaxed binding属性中indent_output的大小写不必与对应枚举常量INDENT_OUTPUT完全一致。这套环境配置应用到自动配置的JsonMapper.BuilderBean 上因此对它和由该 builder 创建的任意 mapper包括自动配置的JsonMapperBean都生效。所有属性定义见 JacksonProperties.java它通过ConfigurationProperties(spring.jackson)绑定还提供date-format、property-naming-strategy、time-zone、locale、default-lenience、constructor-detector等字段。通过定制器 Bean 做编程式微调属性覆盖不了一切的场景比如要按条件设置Spring Boot 提供了两类定制器 Beanorg.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer定制上下文中的JsonMapper.Builder。定制器可以排序——Boot 自带的定制器 order 为 0因此你可以把自己的定制逻辑放在 Boot 的定制之前或之后。org.springframework.boot.jackson.autoconfigure.JsonFactoryBuilderCustomizer定制 builder 及其创建 mapper 所用的JsonFactory也可以通过各种spring.jackson.factory属性配置工厂。模块注册同样有两条自动通道任意tools.jackson.databind.JacksonModule类型的 Bean 都会自动注册到自动配置的JsonMapper.Builder并作用于它创建的所有JsonMapper实例。这是应用级贡献自定义模块的机制为应用新增功能时推荐使用。通过 JavaServiceLoader机制参与发现的模块默认也会被找到并加入自动配置的JsonMapper.Builder。如果不需要这个行为把spring.jackson.find-and-add-modules设为false。用 JacksonComponent 注册自定义序列化器和反序列化器如果你要自己写tools.jackson.databind.ValueSerializer/tools.jackson.databind.ValueDeserializer常规做法是通过模块注册到 JacksonSpring Boot 提供了替代方案org.springframework.boot.jackson.JacksonComponent注解可以直接注册 Spring Bean。它可以直接标注在ValueSerializer、ValueDeserializer或KeyDeserializer实现上也可以标注在把这些类作为内部类的类上。Spring Boot 文档中的示例如下来自 MyJacksonComponent.java使用时把MyObject换成你的对象类型import tools.jackson.core.JsonGenerator; import tools.jackson.core.JsonParser; import tools.jackson.databind.DeserializationContext; import tools.jackson.databind.JsonNode; import tools.jackson.databind.SerializationContext; import tools.jackson.databind.ValueDeserializer; import tools.jackson.databind.ValueSerializer; import org.springframework.boot.jackson.JacksonComponent; JacksonComponent public class MyJacksonComponent { public static class Serializer extends ValueSerializerMyObject { Override public void serialize(MyObject value, JsonGenerator jgen, SerializationContext context) { jgen.writeStartObject(); jgen.writeStringProperty(name, value.getName()); jgen.writeNumberProperty(age, value.getAge()); jgen.writeEndObject(); } } public static class Deserializer extends ValueDeserializerMyObject { Override public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) { JsonNode tree jsonParser.readValueAsTree(); String name tree.get(name).stringValue(); int age tree.get(age).intValue(); return new MyObject(name, age); } } }所有ApplicationContext中的JacksonComponentBean 都会自动注册到 Jackson。由于JacksonComponent元标注了Component常规的组件扫描规则适用。Spring Boot 还提供了org.springframework.boot.jackson.ObjectValueSerializer和org.springframework.boot.jackson.ObjectValueDeserializer基类在序列化对象时是标准 Jackson 类的可用替代细节见其 API 文档。用 JacksonMixin 给已有类混入注解Jackson 支持 mixin可以把额外注解混入目标类已声明的注解。Spring Boot 的 Jackson 自动配置会扫描应用包中用org.springframework.boot.jackson.JacksonMixin标注的类并把它们注册到自动配置的JsonMapper注册由org.springframework.boot.jackson.JacksonMixinModule完成。适合无法修改源码、又想调整某类序列化行为的情况。完全替换默认的 JsonMapper如果需要彻底接管有两种方式定义JsonMapper类型的Bean或者如果更喜欢 builder 方式定义tools.jackson.databind.json.JsonMapper.Builder类型的Bean。两点必须注意定义JsonMapperBean 时建议标注Primary因为它要替换的自动配置JsonMapper本身是Primary的。无论哪种方式这样做都会禁用JsonMapper的全部自动配置——前文的属性绑定、JacksonModule自动注册等都不会再作用于你定义的 Bean。让定制生效于 HTTP 消息转换器JsonMapper定制要影响 MVC/HTTP 客户端的 JSON 转换还需要关注消息转换器这一层如果你提供任何org.springframework.http.converter.json.JacksonJsonHttpMessageConverter类型的 Bean它会替换 MVC 配置中的默认值。也可以声明org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizerBean 来添加转换器或覆盖某个默认转换器。Spring Boot 文档中的示例展示了用自定义JsonMapper构建转换器并同时作用于服务端和客户端完整代码见 MyHttpMessageConvertersConfiguration.javaimport java.text.SimpleDateFormat; import tools.jackson.databind.json.JsonMapper; import org.springframework.boot.http.converter.autoconfigure.ClientHttpMessageConvertersCustomizer; import org.springframework.boot.http.converter.autoconfigure.ServerHttpMessageConvertersCustomizer; import org.springframework.http.converter.HttpMessageConverters.ClientBuilder; import org.springframework.http.converter.HttpMessageConverters.ServerBuilder; import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter; // 关键部分构建自定义 JsonMapper 并贡献给 server 与 client JsonMapper jsonMapper JsonMapper.builder() .defaultDateFormat(new SimpleDateFormat(yyyy-MM)) .build(); static class JacksonConverterCustomizer implements ClientHttpMessageConvertersCustomizer, ServerHttpMessageConvertersCustomizer { private final JsonMapper jsonMapper; JacksonConverterCustomizer(JsonMapper jsonMapper) { this.jsonMapper jsonMapper; } Override public void customize(ClientBuilder builder) { builder.withJsonConverter(new JacksonJsonHttpMessageConverter(this.jsonMapper)); } Override public void customize(ServerBuilder builder) { builder.withJsonConverter(new JacksonJsonHttpMessageConverter(this.jsonMapper)); } }上面的JsonMapper是在定制器内部自行构建的与自动配置的JsonMapper无关这是与替换自动配置 Bean 不同的另一条控制路径适合只希望替换 JSON 转换器所用 mapper 而不想关掉全部自动配置的场景。从 Jackson 2 迁移恢复旧的默认行为对之前使用 Jackson 2 的应用自动配置的JsonMapper可以设置为尽量接近 Spring Boot 当年为 Jackson 2 使用的默认值。把spring.jackson.use-jackson2-defaults设为true即可启用这些默认值缓解迁移过程中的行为差异。验证定制是否生效验证路径就是请求一个 JSON 接口观察输出Spring Boot 应用中的任何RestController在 Jackson 3 位于 classpath 上时默认就渲染 JSON 响应例如示例中的接口在http://localhost:8080/thing上直接返回对象的 JSON 表示。设置了spring.jackson.serialization.indent_outputtrue后响应的 JSON 输出为格式化pretty print形式注册了JacksonComponent序列化器后对应类型的 JSON 结构应与你serialize方法写入的字段一致反序列化方向可提交 JSON 请求验证能否按你的deserialize逻辑还原如果预期看到 JSON 却在浏览器里看到 XML这是浏览器倾向发送偏好 XML 的Accept头导致的换成Accept: application/json请求即可。各路径的取舍能用spring.jackson.*属性解决的不要写定制器需要按条件编程式调整用JsonMapperBuilderCustomizer行为与 Jackson 3 默认差异过大、短期不便调整时才用use-jackson2-defaults过渡只有需要彻底接管时才定义JsonMapper或JsonMapper.BuilderBean并记住它会禁用全部自动配置。更多细节可参考 JSON 特性文档和 Spring MVC 常见问题文档中的 Customize the Jackson JsonMapper 一节。【免费下载链接】spring-bootSpring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.项目地址: https://gitcode.com/gh_mirrors/sp/spring-boot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价