@JsonSerialize注解自定义序列化方式
文章目录
前言
在工作场景里,若要对响应数据执行序列化操作,借助 Jackson 的@JsonSerialize
注解,能够依照指定方式完成序列化任务,利用该注解还能自定义字段的序列化形式。当默认的序列化方法无法契合业务需求时,我们可通过继承StdSerializer
抽象类,并重写其中的serialize
方法,从而实现完全定制化的序列化逻辑。
创建自定义序列化器
继承 StdSerializer
并实现自定义序列化逻辑。以下以 LocalDateTime
转换为 Unix 时间戳为例:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
public class CustomLocalDateTimeSerializer extends StdSerializer<LocalDateTime> {
// 必须提供无参构造器
public CustomLocalDateTimeSerializer() {
this(null);
}
// 构造器指定序列化类型
public CustomLocalDateTimeSerializer(Class<LocalDateTime> t) {
super(t);
}
@Override
public void serialize(
LocalDateTime value,
JsonGenerator gen,
SerializerProvider provider
) throws IOException {
if (value == null) {
gen.writeNull(); // 处理 null 值
return;
}
// 将 LocalDateTime 转为 Unix 时间戳(毫秒)
long timestamp = value.toInstant(ZoneOffset.UTC).toEpochMilli();
gen.writeNumber(timestamp);
}
}
应用自定义序列化器
在需要自定义序列化的字段上使用 @JsonSerialize
注解:
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.time.LocalDateTime;
public class Event {
private String name;
@JsonSerialize(using = CustomLocalDateTimeSerializer.class)
private LocalDateTime eventTime;
// 构造器、Getter/Setter...
}
测试序列化结果
使用 ObjectMapper
序列化对象,验证输出:
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws Exception {
Event event = new Event("Conference", LocalDateTime.now());
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(event);
System.out.println(json);
// 输出示例:{"name":"Conference","eventTime":1672531200000}
}
}
高级用法:全局注册序列化器
若需全局应用自定义序列化器(无需在每个字段单独注解),注册为 Jackson 模块:
import com.fasterxml.jackson.databind.module.SimpleModule;
public class CustomModule extends SimpleModule {
public CustomModule() {
addSerializer(LocalDateTime.class, new CustomLocalDateTimeSerializer());
}
}
// 注册模块
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new CustomModule());
关键点解析
步骤 | 说明 |
---|---|
继承 StdSerializer |
必须指定泛型类型(如 LocalDateTime )并实现 serialize 方法 |
处理 null 值 | 在 serialize 方法中显式处理 value == null 的情况,避免 NPE |
时间转换逻辑 | 示例中将 LocalDateTime 转为 Unix 时间戳,可根据需求修改为其他格式(如字符串) |
注解应用 | @JsonSerialize(using = CustomSerializer.class) 指定字段级序列化器 |
全局注册 | 通过 SimpleModule 实现全局生效,适用于频繁使用的自定义逻辑 |
常见问题解决
问题1:序列化结果不符合预期
- 检查
JsonGenerator
方法:确保使用正确的方法写入数据,如writeNumber()
、writeString()
。 - 验证时区:时间转换时需统一时区(示例中使用
ZoneOffset.UTC
)。
问题2:空指针异常
- 防御性编程:在
serialize
方法中处理value == null
的情况。
问题3:自定义序列化器未生效
- 检查注解位置:确保
@JsonSerialize
应用在正确的字段或Getter
方法上。 - 模块注册顺序:全局模块需在
ObjectMapper
初始化后注册。