@JsonSerialize注解自定义序列化方式

发布于:2025-04-19 ⋅ 阅读:(19) ⋅ 点赞:(0)

@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 初始化后注册。

网站公告

今日签到

点亮在社区的每一天
去签到