1. 前言
在Java开发中我们为了避免过多的魔法值,使用枚举类来封装一些静态的状态代码。但是在将这些枚举的意思正确而全面的返回给前端却并不是那么顺利,我们通常会使用Jackson类库序列化对象为JSON,今天就来讲一个关于使用Jackson序列化枚举的通用性技巧。
2. 通用枚举范式
为了便于统一处理和规范统一的风格,建议指定一个统一的抽象接口,例如:
/** * 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; } }
3. 序列化枚举
如果我们直接使用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);
然后再次执行就会获取我们期望的结果。然而这并不算合理。
4. Spring Boot 中自动全局配置
在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(); } }); }
这样就实现了全局配置。
5. 总结
这里我们介绍了如何定制Jackson库以达到对枚举进行更加友好的序列化的目的。其实不单单枚举,你也可以实现其它序列化,反序列化,时间输出格式的定制。这些特性留给你自己挖掘。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。
- 本文固定链接: https://zxbcw.cn/post/194874/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)