在 Java 开发中我们为了避免过多的魔法值,使用枚举类来封装一些静态的状态代码。但是在将这些枚举的意思正确而全面的返回给前端却并不是那么顺利,我们通常会使用 Jackson 类库序列化对象为 JSON ,今天就来讲一个关于使用 Jackson 序列化枚举的通用性技巧。
为了便于统一处理和规范统一的风格,建议指定一个统一的抽象接口,例如:
/** * The interface Enumerator. */ public interface Enumerator { /** * Code integer. * * @return the integer */ Integer code(); /** * Description string. * * @return the string */ String description(); } 复制代码
我们来写一个实现来标识性别:
public enum GenderEnum implements Enumerator { UNKNOWN(0, "未知"), MALE(1, "男"), FEMALE(2, "女"); private final Integer code; private final String description; GenderEnum(Integer code, String description) { this.code = code; this.description = description; } @Override public Integer code() { return code; } @Override public String description() { return description; } } 复制代码
如果我们直接使用 Jackson 对枚举进行序列化,将只能简单的输出枚举的 String
名称:
@Resource private ObjectMapper objectMapper; @Test void enumTest() { try { String s = objectMapper.writeValueAsString(GenderEnum.MALE); // 输出字符串 MALE System.out.println(s); } catch (JsonProcessingException e) { e.printStackTrace(); } } 复制代码
我们期望将 GenderEnum.MALE
序列化为 {"code":1,"description":"男"}
。我们可以向 ObjectMapper
定制化一个 Module
来实现这种个性化需求:
// 声明一个简单Module 对象 SimpleModule module = new SimpleModule(); // 给Module 添加一个序列化器 module.addSerializer(Enumerator.class, new JsonSerializer<Enumerator>() { @Override public void serialize(Enumerator value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 开始写入对象 gen.writeStartObject(); // 分别指定 k v code description gen.writeNumberField("code",value.code()); gen.writeStringField("description",value.description()); // 显式结束操作 gen.writeEndObject(); } }); // 注册 Module objectMapper.registerModule(module); 复制代码
然后再次执行就会获取我们期望的结果。然而这并不算合理。
在 Spring Boot 应用中我们希望能全局配置。 Spring Boot 的自动配置为我们提供了一个个性化定制 ObjectMapper
的可能性,你只需要声明一个 Jackson2ObjectMapperBuilderCustomizer
并注入 Spring IoC :
@Bean public Jackson2ObjectMapperBuilderCustomizer enumCustomizer(){ return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.serializerByType(Enumerator.class, new JsonSerializer<Enumerator>() { @Override public void serialize(Enumerator value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeStartObject(); gen.writeNumberField("code",value.code()); gen.writeStringField("description",value.description()); gen.writeEndObject(); } }); } 复制代码
这样就实现了全局配置。
这里我们介绍了如何定制 Jackson 库以达到对枚举进行更加友好的序列化的目的。其实不单单枚举,你也可以实现其它序列化,反序列化,时间输出格式的定制。这些特性留给你自己挖掘。多多关注: 码农小胖哥 获取更多开发技巧。
关注公众号:Felordcn获取更多资讯
个人博客:https://felord.cn