1 简介
在Java开发中,为了避免魔法值过多,我们使用枚举类来封装一些静态状态码。 然而,要将这些枚举的含义正确、全面地返回给前端,并不是那么顺利。 我们通常使用类库将对象序列化为 JSON。 今天我将讨论有关使用序列化枚举的通用技术。
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. 序列化枚举
如果我们直接序列化枚举,我们将简单地输出枚举的名称:
@Resource
private ObjectMapper objectMapper;
@Test
void enumTest() {
try {
String s = objectMapper.writevalueAsString(GenderEnum.MALE);
// 输出字符串 MALE
System.out.println(s);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
我们期望 .MALE 被序列化为 {"code":1,"":"Male"}。 我们可以定制一个来实现这一个性化需求:
// 声明一个简单Module 对象
SimpleModule module = new SimpleModule();
// 给Module 添加一个序列化器
module.addSerializer(Enumerator.class, new JsonSerializer() {
@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. Boot中自动全局配置
在Boot应用中,我们希望进行全局配置。 Boot的自动配置为我们提供了个性化定制的可能,只需要声明一个并注入IoC即可:
@Bean
public Jackson2ObjectMapperBuilderCustomizer enumCustomizer(){
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.serializerByType(Enumerator.class, new JsonSerializer() {
@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();
}
});
}
这样就实现了全局配置。
5. 总结
这里介绍如何自定义该库来实现更友好的枚举序列化。 其实不只是枚举,你还可以实现其他的序列化、反序列化、以及时间输出格式的自定义。 这些功能留给您去发现。 多多关注:码农小胖,了解更多开发技巧。