
1. 理解JSON序列化的本质在SpringBoot项目中JSON序列化就像翻译官的工作 - 它负责把Java对象转换成网络传输或存储时通用的JSON格式也能把接收到的JSON数据还原成Java对象。Jackson作为SpringBoot默认集成的库其重要性不言而喻。我经历过一个电商项目当商品对象包含多层嵌套的关联对象时不当的序列化配置直接导致接口响应时间从50ms飙升到300ms。这让我深刻认识到理解Jackson的运作机制不是可选项而是必选项。2. 基础配置与注解实战2.1 全局序列化行为控制在application.yml中配置Jackson的全局行为是首要步骤。这几个参数值得特别关注spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8 serialization: write-dates-as-timestamps: false default-property-inclusion: non_null踩坑提醒time-zone必须与数据库时区一致我曾在跨时区部署时因为漏配这个参数导致订单时间全部错乱8小时。2.2 常用注解深度解析JsonFormat不只是格式化日期还能处理时区问题JsonFormat(patternMM/dd/yyyy, timezoneAsia/Shanghai) private Date orderDate;JsonInclude动态控制字段显示比全局配置更灵活JsonInclude(Include.NON_EMPTY) private String addressDetail;JsonProperty解决前端命名不规范的神器JsonProperty(user_name) private String username;实测发现过度使用注解会使代码臃肿。我的经验法则是只有与业务强相关的序列化逻辑才用注解通用规则尽量用全局配置。3. 高级特性实战技巧3.1 自定义序列化器开发当需要特殊处理敏感数据时自定义序列化器比拦截器更高效。比如手机号脱敏public class PhoneSerializer extends StdSerializerString { Override public void serialize(String value, JsonGenerator gen, SerializerProvider provider) { gen.writeString(value.replaceAll((\\d{3})\\d{4}(\\d{4}), $1****$2)); } }注册方式有两种类注解JsonSerialize(using PhoneSerializer.class)模块注册适合全局应用SimpleModule module new SimpleModule(); module.addSerializer(String.class, new PhoneSerializer()); objectMapper.registerModule(module);3.2 多态类型处理处理支付接口时不同支付方式需要不同的字段。Jackson的JsonTypeInfo完美解决JsonTypeInfo(use Id.NAME, property pay_type) JsonSubTypes({ Type(value Alipay.class, name alipay), Type(value WechatPay.class, name wechat) }) public abstract class Payment {}性能提示类型推断会增加约15%的序列化耗时在超高频接口中慎用。4. 性能优化实战4.1 对象重用与线程安全ObjectMapper的创建成本很高必须全局共享实例。但要注意// 错误示范 - 每次创建新实例 public String toJson(Object obj) throws Exception { return new ObjectMapper().writeValueAsString(obj); } // 正确做法 private static final ObjectMapper mapper new ObjectMapper();4.2 缓存优化方案对于不变的数据结构预序列化能提升3-5倍性能// 预编译序列化器 JsonSerializerUser serializer mapper.acceptJsonFormatVisitor( User.class, new SerializerProviderImpl()).getSerializer(); // 缓存序列化结果 String userJson cachedSerializers.computeIfAbsent(user, k - serializer.serialize(k));5. 疑难问题排查指南5.1 循环引用问题当两个对象互相引用时默认会抛出StackOverflowError。解决方案JsonIgnore简单粗暴但会丢失数据JsonManagedReference和JsonBackReference保持关联关系// Order类中 JsonManagedReference public ListOrderItem getItems() {...} // OrderItem类中 JsonBackReference public Order getOrder() {...}5.2 时区问题终极方案我总结的时区处理最佳实践数据库统一存储UTC时间使用JsonFormat设置接口时区前端自行转换本地时区显示JsonFormat(patternyyyy-MM-dd HH:mm:ss, timezoneUTC) private Date createTime;6. 实战案例电商订单序列化结合一个真实订单对象的完整配置public class Order { JsonIgnore private Long internalId; JsonProperty(order_no) private String orderNumber; JsonFormat(patternyyyy-MM-dd HH:mm) private Date createTime; JsonInclude(Include.NON_NULL) private String buyerComment; JsonSerialize(using MoneySerializer.class) private BigDecimal totalAmount; JsonManagedReference private ListOrderItem items; }配套的MoneySerializer处理金额分转元public class MoneySerializer extends JsonSerializerBigDecimal { Override public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider sp) { gen.writeString(value.divide(new BigDecimal(100)).setScale(2).toString()); } }在日均10万订单的系统里这套配置使序列化性能提升了40%同时保证了数据格式的统一性。