BUG描述

在使用SpringBoot自带的jackson处理客户端提交的消息体反序列化时,遇到一个非常棘手的情况

客户端发送如下json

{"content":"6545566","type":"1","to":"xxx"}

Java对应实体类

abstract class BaseMessage implements Message{

    @JsonIgnore
protected String from;
@JsonIgnore
protected String address;
@JsonIgnore
protected Date sendTime; protected MessageType type; /**
* 客户端信息的处理方法
* @return netty socket回复对象
*/
@Override
public abstract BaseResult handle();
}

MessageType枚举类

/**
* @author Evan
*/
public enum MessageType {
/**
*
*/
TEXT(1),
/**
*
*/
IMAGE(2); private int index; MessageType(int index) {
this.index = index;
} public int getValue() {
return index;
}
}

在反序列化的时候出现以下错误

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "type"



报错信息说明的很清楚,枚举属性type在反序列化的时候无法识别.其实也可以理解,枚举本身就是一个很特殊的数据类型Jackson无法正常的序列化也正常

解决思路

其实这个问题一开始真是难到我了,按之前的项目经验来说,在处理前端数据对应的实体类的属性一般是不会使用枚举类型的一般这种类似的属性我们都要求客户端以整数值提交后台,后台实体类也按integer类型保存.此类问题真的少见

面向Google编程,得到最靠谱最简单的方案是在枚举类使用@JsonCreator注解标识一个工厂方法创建正确的枚举值,但是不知道为什么在我这里毫无效果

查阅资料后了解到Jackson是允许为单独属性定义转换器的

实现如下代码

/**
* @author Evan
*/
public class MessageTypeConverter implements Converter<String, MessageType> { @Override
public MessageType convert(String value) {
return MessageType.valueOf(Integer.parseInt(value));
} /**
* 输入值类型
* @param typeFactory
* @return
*/
@Override
public JavaType getInputType(TypeFactory typeFactory) {
return typeFactory.constructType(String.class);
} /**
* 转换器输出值类型
* @param typeFactory
* @return
*/
@Override
public JavaType getOutputType(TypeFactory typeFactory) {
return typeFactory.constructType(MessageType.class);
}
}

其中关键就在于convert方法,我们要求前台提交一个String类型的数值给我们,我们在根据这个数值给转换器该属性准确的值

枚举类MessageTpe添加valueOf方法

 public static MessageType valueOf(int value) {
switch (value) {
case 1:
return TEXT; case 2:
return IMAGE;
default:
return null;
}
}

实体类BaseMessagetype属性添加注解指定反序列转换器

/**
* @author Evan
*/
abstract class BaseMessage implements Message{ @JsonIgnore
protected String from;
@JsonIgnore
protected String address;
@JsonIgnore
protected Date sendTime;
@JsonDeserialize(converter = MessageTypeConverter.class)
protected MessageType type; /**
* 客户端信息的处理方法
* @return netty socket回复对象
*/
@Override
public abstract BaseResult handle();
}

那么就可以从一个数值得到正确的对应的枚举类型了

emmmmmmmmmmm.........问题是解决了.....

好像哪里不对劲

他喵的要switch我还定义啥枚举啊

修改枚举类MessageTypevalueOf方法

    public static MessageType valueOf(int value) {
for (MessageType type : MessageType.values()){
if (type.getValue() == value){
return type;
}
}
return null;
}

舒服了.....

如果大家头更好的方法欢迎评论区讨论交流~

Jackson反序列化枚举类型解决方案的更多相关文章

  1. 由@Convert注解引出的jackson对枚举的反序列化规则

    对于一些状态字段以前时兴用常量,现在时兴用枚举,虽然阅读体验极佳,但是传值的时候还是会有些麻烦,需要设置一下转换器.比如: class A{ @Convert(converter=TestTypeCo ...

  2. 自定义fastjson对枚举类型的序列化及反序列化过程

    通常,fastjson在序列化及反序列化枚举时,一般以下几种策略: 1).根据枚举的name值序列化及反序列化(默认) 2).根据枚举的ordinal序列化及反序列化 3).根据枚举的toString ...

  3. spring-boot rest controller 使用枚举作为参数,重写反序列化实现任意值转枚举类型

    目录 BaseEnum MyEnum StringToEnumConverterFactory FormatterConfig DTO RestController 参考 BaseEnum packa ...

  4. jackson 转换 enum 类型

    REST API 接口要求 requster json 的 lifeCycle 域只能填 YOUNG, OLD,对于其他的 lifeCycle,都要给 requester 返回 bad request ...

  5. 【hibernate postgresql】注解@TypeDef/@Enumerated/数据库字段gender为枚举类型,从前台接受到实体后进行保存报错:org.postgresql.util.PSQLException: ERROR: column "gender" is of type gender but expression is of type character varying

    数据库字段gender为枚举类型,从前台接受到实体后进行保存报错:org.postgresql.util.PSQLException: ERROR: column "gender" ...

  6. Python 中的枚举类型~转

    Python 中的枚举类型 摘要: 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期.月份.状态等. 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表 ...

  7. 【转】java枚举类型enum的使用

    原文网址:http://blog.csdn.net/wgw335363240/article/details/6359614 java 枚举类型enum 的使用 最近跟同事讨论问题的时候,突然同事提到 ...

  8. 枚举类型的单例模式(java)

    Inspired by Effective Java. Singleton模式是在编程实践中应用最广泛的几种设计模式之一.以前知道的,实现单例的方法有两种(下面的A.B).刚刚在读<Effect ...

  9. 第3条:用私有构造器或者枚举类型强化Singleton属性

    Singleton是指仅仅被实例化一次的类.通过被用来代表那些本质上唯一的系统组件,比如窗口管理器或者文件系统. 在http://www.cnblogs.com/13jhzeng/p/5256424. ...

随机推荐

  1. 1 Spark概述

     第1章 Spark概述 1.1 什么是Spark Spark是一种快速.通用.可扩展的大数据分析引擎,2009年诞生于加州大学伯克利分校AMPLab,2010年开源,2013年6月成为Apache孵 ...

  2. 初学Linux (Linux_note)

    根目录:/ /root: 存放root用户相关文件 /home: 存放不同用户的相关文件 /bin: 存放常用命令的目录 /sbin: 要具有一定权限才可以使用的命令 /mnt: 默认挂载光驱和软驱的 ...

  3. 四则运算(C语言实现)

    四则运算(c语言实现) 合伙人:魏甫——3118004973  ,温钦益——3118004975 https://github.com/iamdate/work/tree/master 一.项目及其要 ...

  4. .sync 修饰符

    vue 修饰符sync的功能是:当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定 //写一个(子)组件Child.vue <template> <div c ...

  5. 简述HBase的Bulk Load

    为什么用Bulk load? 批量加载数据到HBase集群,有很多种方式,比如利用 HBase API 进行批量写入数据.使用Sqoop工具批量导数到HBase集群.使用MapReduce批量导入等等 ...

  6. 设计模式C++模板(Template)模式

    设计模式C++描述----02.模板(Template)模式(转载) 一. 问题 在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现, ...

  7. 加载PHP的配置扩展文件

    一.在PHP的安装目录中去创建一个  php.ini  的配置文件 复制php.ini-development文件,修改成php.ini文件(注意:不要多加一个空格或标点什么的).其中 php.ini ...

  8. 每日JS逆向练习之斗鱼登录密码加密,今天你练了吗?

    一切的基本功都是为后期调试滑块验证码准备的. 有兴趣的关注一下知识图谱与大数据公众号,当然不关注也无所谓.今天来看看斗鱼登录密码加密,正所谓熟能生巧,这种简单一点的基本3-5分钟就要能抠出来,有兴趣得 ...

  9. Sequence (矩阵快速幂+快速幂+费马小定理)

            Holion August will eat every thing he has found. Now there are many foods,but he does not wa ...

  10. 【问题】【SpringBoot】记一次springboot框架下用jackson解析RequestBody失败的问题

    最近项目中遇到了一个问题,费好大劲才发现问题所在,并且修复了问题,下面分享一下这个问题的定位和修复的新路旅程. 先说下背景:该项目用的是SpringBoot框架,主要功能为对外提供一些Restful ...