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. python中a, b = a, a + b这条语句是如何执行的?

    a,b=b,a+b,这条语句在"理解"上还是与C语言有些差别的.在Python中,可以做下面的方式理解:首先,把等号右边的算式分别算完再说,然后按照一一对应的关系把值赋给等号左边的 ...

  2. tp6 不能使用vendor

    从thinkphp 5.1.x后vendor的使用方法发生变化,文档又没有详细说明.官方真的太坑了! 在thinkPHP 5.1.X后新版取消了Loader::import方法以及import和ven ...

  3. Java算法——回溯法

    回溯法一种选优搜索法,又称试探法.利用试探性的方法,在包含问题所有解的解空间树中,将可能的结果搜索一遍,从而获得满足条件的解.搜索过程采用深度遍历策略,并随时判定结点是否满足条件要求,满足要求就继续向 ...

  4. 微信支付宝个人免签约即时到帐接口开发附demo

    支付界面: 扫码支付界面: 付成功后可以跳转到你程序指定的地址! demo: http://likeyunba.com/WeChat-Pay/

  5. Docker 最常用的镜像命令和容器命令

    本文列出了 Docker 使用过程中最常用的镜像命令和容器命令,以及教大家如何操作容器数据卷,实现容器数据的备份.熟练练习这些命令以后,再来一些简单的应用部署练习,大家就可以学习 Docker 的镜像 ...

  6. 题解 P2426 【删数】

    洛谷题目传送门 一眼看去:区间DP 数据范围:三重循环 好了不装B了,开始说正事 这题非常明显是区间DP. 按照惯例,先定义状态. 分析题目,发现除了区间左端点和右端点之外,什么也不需要加进状态里.因 ...

  7. 揭秘!containerd 镜像文件丢失问题,竟是镜像生成惹得祸

    导语 作者李志宇,腾讯云后台开发工程师,日常负责集群节点和运行时相关的工作,熟悉 containerd.docker.runc 等运行时组件.近期在为某位客户提供技术支持过程中,遇到了 contain ...

  8. 轻量化模型训练加速的思考(Pytorch实现)

    0. 引子 在训练轻量化模型时,经常发生的情况就是,明明 GPU 很闲,可速度就是上不去,用了多张卡并行也没有太大改善. 如果什么优化都不做,仅仅是使用nn.DataParallel这个模块,那么实测 ...

  9. 最佳实践:Pulsar 为批流处理提供融合存储

    非常荣幸有机会和大家分享一下 Apache Pulsar 怎样为批流处理提供融合的存储.希望今天的分享对做大数据处理的同学能有帮助和启发. 这次分享,主要分为四个部分: 介绍与其他消息系统相比, Ap ...

  10. 【Android】SlidingTabLayout实现标题栏,教你制作title标题 简单易学。

    SlidingTabLayout 作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 微博:http://weibo.com/m ...