1. 前言
在Java开发中我们为了避免过多的魔法值,使用枚举类来封装一些静态的状态代码。但是在将这些枚举的意思正确而全面的返回给前端却并不是那么顺利,我们通常会使用Jackson类库序列化对象为JSON,今天就来讲一个关于使用Jackson序列化枚举的通用性技巧。
2. 通用枚举范式
为了便于统一处理和规范统一的风格,建议指定一个统一的抽象接口,例如:
public interface Enumerator {
Integer code();
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;
}
}
3. 序列化枚举
如果我们直接使用Jackson对枚举进行序列化,将只能简单的输出枚举的String名称
但是我们期望将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);
然后再次执行就会获取我们期望的结果。然而这并不算合理。
4. Spring Boot 中自动全局配置
Spring Boot应用中我们希望能全局配置。Spring Boot的自动配置为我们提供了一个个性化定制ObjectMapper的可能性,你只需要声明一个Jackson2ObjectMapperBuilderCustomizer并注入Spring IoC:
@Component
public class Jackson2ObjectEnumCustomizer {
@Bean
public org.springframework.boot.autoconfigure.jackson.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.getCode());
gen.writeStringField("msg",value.getMsg());
gen.writeEndObject();
}
});
}
}