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


    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
      
      • 1
      • 2
      • 3
      • 4
    2. 在mybatis查询到结果反序列的时候,可以使用mybatis的类型处理器TypeHandler,来做反序列化时候判断。
      在配置文件中指定默认的枚举类型处理器

      mybatis:
        configuration:
          default-enum-type-handler: com.example.csdn.enum_test.MyEnumTypeHandler
      
      • 1
      • 2
      • 3
      // 自定义枚举处理器,继承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;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
    3. 解释一下: 真正有这种需求的人可以考虑使用上述方法,其他情况下不建议这样子操作,毕竟如果对方传个莫名其妙的东西,你也不知道对方到底传递什么非法内容,直接转null了,而且在controller层dto对象中定义枚举,也是一种校验,直接不符合规则,更早报错。

    3. 代码验证

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

    1. 在配置文件中配置:

      spring:
        jackson:
          deserialization:
            READ_UNKNOWN_ENUM_VALUES_AS_NULL: true
      
      • 1
      • 2
      • 3
      • 4
    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);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

      在这里插入图片描述

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

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

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

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

      mybatis:
        configuration:
          default-enum-type-handler: com.example.csdn.enum_test.MyEnumTypeHandler
      
      • 1
      • 2
      • 3
      @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
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

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

  • 相关阅读:
    Java中this关键字的常见用法
    还在拿flex进行布局吗?快来试试grid网格布局吧
    如何用Excel做最小二乘法②
    HTML 的学习-1|HTML 简介
    【Web前端】CSS-盒子模型
    中英文说明书丨SYSY NeuN抗体参数及应用实例
    PSSecurityException
    cadence SPB17.4 - allegro - DRC ERROR - Soldermask to Shape Spacing
    MySQL排查篇:该如何定位并解决线上突发的Bug与疑难杂症?
    背包问题(01背包,完全背包,多重背包,用二进制优化的多重背包,分组背包)
  • 原文地址:https://blog.csdn.net/xueyijin/article/details/126067359