zoukankan      html  css  js  c++  java
  • JSON类库Jackson优雅序列化Java枚举类

    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库以达到对枚举进行更加友好的序列化的目的。其实不单单枚举,你也可以实现其它序列化,反序列化,时间输出格式的定制。这些特性留给你自己挖掘。多多关注:码农小胖哥 获取更多开发技巧。

    关注公众号:Felordcn 获取更多资讯

    个人博客:https://felord.cn

  • 相关阅读:
    [Mac] 获取cpu信息
    [gcc warnings] -Wtrigraph warnings
    查看SSD寿命
    [linux] 查看SATA速度和具体设备
    [raspberry p3] [suse] 安装maven
    文本处理例子
    容器中用shell脚本启动如何优雅关闭(传送kill SIGTERM信号)
    kubernetes deployment 使用镜像摘要发布新版本
    Yearning sql工单系统 自动执行工单python脚本
    Kubernetes 企业发行版、容器Pass平台 OpenShift4.3 规划裸机部署
  • 原文地址:https://www.cnblogs.com/felordcn/p/13175221.html
Copyright © 2011-2022 走看看