若枚举映射的值不存在,则不进行反序列化

1. 前言

  1. 在开发中会经常使用到枚举,而使用其的时候,可能会出现传的值并不在枚举定义的值中,则报错如下(无法转换):
    在这里插入图片描述
  2. 出现这样子的原因就是对应的值并不存在枚举里面,从而无法进行正常的对象转换赋值,一般经常出现场景无非两个地方:
    一、controller层接口被外部调用的时候
    二、mybatis查询结果出来反序列化的时候
  3. 某天突发想法,为什么在反序列化的时候,没有传入的值并不在枚举映射的值时候,不报错,自动赋值为null呢

2. 先说结论

  1. 在controller层接口接收参数的时候,是使用objectMapper进行反序列化的,而里面有个配置:READ_UNKNOWN_ENUM_VALUES_AS_NULL,意思就是:获取到不认识的枚举值赋值为null,不报错
    在springboot中可在yml配置文件中写

    spring:
      jackson:
        deserialization:
          READ_UNKNOWN_ENUM_VALUES_AS_NULL: true
    
  2. 在mybatis查询到结果反序列的时候,可以使用mybatis的类型处理器TypeHandler,来做反序列化时候判断。
    在配置文件中指定默认的枚举类型处理器

    mybatis:
      configuration:
        default-enum-type-handler: com.example.csdn.enum_test.MyEnumTypeHandler
    
    // 自定义枚举处理器,继承mybatis自带的EnumTypeHandler,简化优化需写的代码
    // @MappedTypes 的意思是用于指明该TypeHandler实现类能够处理的Java 类型的集合
    // @MappedTypes({Enum.class})的意思是:只有是枚举类型的才会走下面的处理器
    @MappedTypes({Enum.class})
    public class MyEnumTypeHandler<E extends Enum<E>> extends EnumTypeHandler<E> {
    
    	// 枚举类型对应的class对象
        private final Class<E> type;
    
        public MyEnumTypeHandler(Class<E> type) {
            super(type);
            this.type = type;
        }
    
        @Override
        public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
            String s = rs.getString(columnName);
            // 取到枚举所有值
            final Field[] declaredFields = type.getFields();
            // 如果从库里面取到的值,存在枚举值中的一个
            // 则 直接转枚举,否则,直接负责为null
            return Arrays.stream(declaredFields).anyMatch(field -> field.getName().equals(s))
                    ? Enum.valueOf(type, s) : null;
        }
    }
    
  3. 解释一下: 真正有这种需求的人可以考虑使用上述方法,其他情况下不建议这样子操作,毕竟如果对方传个莫名其妙的东西,你也不知道对方到底传递什么非法内容,直接转null了,而且在controller层dto对象中定义枚举,也是一种校验,直接不符合规则,更早报错。

3. 代码验证

1. controller层接口遇到枚举映射值不存在情况

  1. 在配置文件中配置:

    spring:
      jackson:
        deserialization:
          READ_UNKNOWN_ENUM_VALUES_AS_NULL: true
    
  2. 代码:

    @Data
    public class testDto {
        private String name;
        private test_enum pwd;
    }
    
    
    public enum test_enum {
        A, B, C,
    }
    
    @RestController
    public class EnumController {
    
        @PostMapping("/enum/test")
        public void test2(@RequestBody testDto testDto){
            System.out.println(testDto);
        }
    }
    

    在这里插入图片描述

2. mybatis中枚举映射值不存在

  1. 不加自定义类型处理器的情况下:

    在这里插入图片描述
    在这里插入图片描述

  2. 在加入自定义处理器的情况下:
    配置文件中配置:

    mybatis:
      configuration:
        default-enum-type-handler: com.example.csdn.enum_test.MyEnumTypeHandler
    
    @MappedTypes({Enum.class})
    public class MyEnumTypeHandler<E extends Enum<E>> extends EnumTypeHandler<E> {
    
    	// 枚举类型对应的class对象
        private final Class<E> type;
    
        public MyEnumTypeHandler(Class<E> type) {
            super(type);
            this.type = type;
        }
    
        @Override
        public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
            String s = rs.getString(columnName);
            // 取到枚举所有值
            final Field[] declaredFields = type.getFields();
            // 如果从库里面取到的值,存在枚举值中的一个
            // 则 直接转枚举,否则,直接负责为null
            return Arrays.stream(declaredFields).anyMatch(field -> field.getName().equals(s))
                    ? Enum.valueOf(type, s) : null;
        }
    }
    

    在这里插入图片描述
    在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值