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

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
    评论
在使用fastjson进行反序列化Java中实体的枚举字段时,如果出现错误,可以检查以下几个方面: 1. 确认枚举类中的枚举是否能够正确映射。fastjson默认使用枚举的名称进行序列化和反序列化,因此需要确保枚举的名称和实际之间的映射关系正确。 2. 确认实体类中的枚举字段的类型是否正确。如果枚举字段的类型不是枚举类本身,而是其它类型(如String),则需要使用@JSONField注解来指定fastjson进行序列化和反序列化时应该使用的类型。例如: ``` public class Entity { @JSONField(deserializeUsing = ColorDeserializer.class) private Color color; // ... } ``` 在这个例子中,ColorDeserializer是一个自定义的反序列化器,用于将枚举的名称转换为枚举对象。在实体类中使用@JSONField注解指定该字段应该使用ColorDeserializer进行反序列化。 3. 如果仍然出现错误,可以尝试使用fastjson的自定义反序列化器来处理枚举字段。例如: ``` public class ColorDeserializer implements ObjectDeserializer { @Override public Color deserialze(DefaultJSONParser parser, Type type, Object fieldName) throws JSONException { String value = parser.getLexer().stringVal(); for (Color color : Color.values()) { if (color.name().equalsIgnoreCase(value)) { return color; } } throw new JSONException("Invalid color value: " + value); } @Override public int getFastMatchToken() { return JSONToken.LITERAL_STRING; } } ``` 然后,在进行反序列化时,可以将ColorDeserializer传递给ParserConfig对象: ``` ParserConfig.getGlobalInstance().putDeserializer(Color.class, new ColorDeserializer()); ``` 这样,fastjson就会使用ColorDeserializer来处理枚举字段反序列化
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值