jackson多态序列化与反序列化
前几天遇到个问题,场景大概是 list 中既有父类又有子类,在反序列化时丢掉了子类的信息。解决这个问题也没花多少时间,不过还是打算记录下。参考链接如下:
Jackson JSON - Using @JsonTypeInfo annotation to handle polymorphic types
我使用 Jackson 实现序列化和反序列化。它在处理多态序列化时的思路是,构造一个起到标识作用的成员变量,并将该成员变量序列化到最终的字符串中,这样在反序列化的时候,jackson一看到这个标识符就知道该朝着哪个类进行反序列化了。
场景
父类:
public abstract class Shape {}
两个子类:
@Data
@ToString
public class Circle extends Shape {int radius;public static Circle of(int radius){Circle circle = new Circle();circle.setRadius(radius);return circle;}}
@Data
@ToString
public class Rectangle extends Shape {private int w;private int h;public static Rectangle of(int w, int h) {Rectangle rectangle = new Rectangle();rectangle.setH(h);rectangle.setW(w);return rectangle;}
}
构建 list:
@Data
@ToString
public class View {private List<Shape> shapes;
}
序列化与反序列化的代码:
public class MainExample {public static void main(String[] args) throws Exception {View view = new View();view.setShapes(new ArrayList<Shape>() {{add(Rectangle.of(3, 6));add(Circle.of(5));}});System.out.println("---- serializing ---");ObjectMapper om = new ObjectMapper();String s = om.writeValueAsString(view);System.out.println(s);System.out.println("--- deserializing ---");View view1 = om.readValue(s,View.class);System.out.println(view1);}
它序列化以及反序列化后的结果:
---- serializing ---
{"shapes":[{"className":"rectangle1","w":3,"h":6},{"className":"circle1","radius":5}]}
--- deserializing ---
View(shapes=[Rectangle(w=3, h=6), Circle(radius=5)])
很明显,无论是 Rectangle 还是 Circle,在序列化后除了自己本省的属性对应的键值对外,各自都多了一个键值对,这个多出来的就是写进的子类信息。靠多出来的这个键值对,就可以保障反序列化的结果是正确的。
正如开头提及的,Jackson是将子列的信息写到了序列化后的字符串中,那具体是怎么写的呢?
它是这么写的:
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "className" ,visible = false)public abstract class Shape {}
@JsonTypeInfo
:Json类型信息,@JsonSubTypes
: Json子类型。纠结这两个准确的意思很没有意思,也不是很必要,必要的是这两个货后面跟着的括弧中的那帮玩意到底表示什么。
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "className" ,visible = false)
@JsonSubTypes({@JsonSubTypes.Type(value = Rectangle.class, name = "rectangle1"),@JsonSubTypes.Type(value = Circle.class, name = "circle1")
})
这两个注解干了一件这样的事情:
include = As.PROPERTY
表示在 Shape
中添加一个成员变量(这个成员变量其实充当了一个类型标识符的作用),父类里面有这个变量,子类当然也就继承到了;property = "className"
表示这个成员变量的名字叫“className”,当然你可以写成别的阿猫阿狗;visible = false
表示“className”这个成员变量在反序列化的时候要被“剔除”掉,也就是说该属性不参与反序列化;use = Id.NAME
表示成员变量className对应的值由用户自己定义,只要不重复就行。那这个值到底是什么呢,@JsonSubTypes.Type(value = Rectangle.class, name = "rectangle1")
表示 Rectangle
的实例中成员变量className
的值是rectangle1
,Circle
也是同样的表示方式。
所以就出现可这样的序列化结果:
---- serializing ---
{"shapes":[{"className":"rectangle1","w":3,"h":6},{"className":"circle1","radius":5}]}
子类的类型信息被“塞到”序列化后的字符串中。
放反序列化的时候,jackson 一看到 rectangle1
就知道这个json字符串要向 Rectangle.class
反序列化,看到 circle1
就向 Circle.class
反序列化。说白了,就是在序列化后的json字符串中添加了一个具有标志作用的键值对,Jackson通过这个键值对确定json应该朝着那个类反序列化。
稍稍变一丢丢
先看啊,序列化的字符串中多了个键值对(虽说反序列化时又给去掉了),假如我要将序列化后的字符串保存起来,mybatis中存json的场景在开发中可是经常会出现的,对象序列化后平白无故多了一些信息,而且还給保存下来了,总归觉得有点别扭。
我着实遇到过这样的场景:创建的 List<object>
需要持久化到 MySQL,并且还要返回给前端。持久化要求序列化和反序列化必须成功。返回给前端要求序列化后不能出现多余的键值对。
如何既能不多信息,又能保证多态反序列化结果正确呢?很简单,在类中找到一个字段,要求不同子类中这个字段的值是不一样的,甚至子类和父类中这个字段的值也是不一样的,拿这个字段作为反序列化的区分标志就行了。
上面的场景改一下:
@Data
@ToString
public class Circle extends Shape {int radius;private String type = "CIR";public static Circle of(int radius){Circle circle = new Circle();circle.setRadius(radius);return circle;}}
@Data
@ToString
public class Rectangle extends Shape {private int w;private int h;private String type = "REC";public static Rectangle of(int w, int h) {Rectangle rectangle = new Rectangle();rectangle.setH(h);rectangle.setW(w);return rectangle;}
}
@JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "type" ,visible = true)
@JsonSubTypes({@JsonSubTypes.Type(value = Rectangle.class, name = "REC"),@JsonSubTypes.Type(value = Circle.class, name = "CIR")
})
public abstract class Shape {}
序列化与反序列化结果:
---- serializing ---
{"shapes":[{"w":3,"h":6,"type":"REC"},{"radius":5,"type":"CIR"}]}
--- deserializing ---
View(shapes=[Rectangle(w=3, h=6, type=REC), Circle(radius=5, type=CIR)])
至于过程这个自己分析啦,很简单的。
jackson多态序列化与反序列化相关推荐
- java为什么序列化不一致_java – 为什么Jackson多态序列化在列表中不起作用?
杰克逊正在做一些真正奇怪的事情,我找不到任何解释.我正在进行多态序列化,当一个对象独立时它可以很好地工作.但是,如果将相同的对象放入列表并对列表进行序列化,则会删除类型信息. 它丢失类型信息的事实将导 ...
- Jackson 自定义序列化和反序列化
目录 1. 创建序列化类 2. 创建反序列化类 3. 实体类字段添加注解 4. 反序列操作 5. 序列化操作 1. 创建序列化类 继承JsonSerializer或者StdSerializer,添加泛 ...
- hutol json null值没了_JSON数据处理框架Jackson精解第一篇-序列化与反序列化核心用法...
Jackson是Spring Boot默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的,没有这种限制.它提供了很 ...
- jackson (json、xml的序列化与反序列化)
jackson用于java对象到json的序列化与反序列化.还支持xml格式. jackson用于实现json与java对象的序列与反序列化.web service要实现跨机器传送对象那么就需要有一种 ...
- jackson 序列化_jackson序列化与反序列化的应用实践
作者 | zhouweixin 来源 | urlify.cn/iEbiAz 66套java从入门到精通实战课程分享 1 相关概念 序列化: 把对象转换为字节序列的过程称为对象的序列化 反序列化: 把字 ...
- Jackson序列化和反序列化
1,下载Jackson工具包(jackson-core-2.2.3.jar jackson-annotations-2.2.3.jar jackson-databind-2.2.3.jar ) j ...
- jackson驼峰转下划线注解_jackson序列化与反序列化的应用实践
作者 | zhouweixin 来源 | urlify.cn/iEbiAz 66套java从入门到精通实战课程分享 1 相关概念 序列化: 把对象转换为字节序列的过程称为对象的序列化 反序列化: 把字 ...
- Jackson对泛型的序列化和反序列化方法汇总
转载自:https://www.cnblogs.com/EasonJim/p/7919422.html 说明:Jackson对于简单泛型是可以正常操作的,但是如果对于太过于复杂的泛型类有时会不成功.目 ...
- 程序验证Jackson反序列化的规则、Jackson序列化与反序列化关键方法程序详细分析
目录 0. 为什么要做这个分析 1. Jackson反序列化时,无参构造.有参构造的执行顺序[附程序截图] 1.1 没有无参构造时: 1.2 无参构造和有参构造方法都有的时候先走无参构造: 2. Ja ...
最新文章
- Kinect for windows的脸部识别
- html5 jq图片效果,HTML5 jQuery可左右滑动拖拉的照片处理前后对比界面
- iOS瀑布流实现(Swift)
- mongodb php 扩展 linux,CentOS Linux 安装PHP的MongoDB扩展
- 《飞鸽传书》把写程序和文学创作相提并论
- Redis-列表(List)基础
- 输入一批整数,输出最大最小值,输入0结束
- Android 中的MVP 模式
- 注意一些坑,从app跳转到qq聊天界面。
- 广义典型相关分析_数学建模/机器学习:广义加性模型(GAM)及其Python实现
- java 类的继承 例题_Java_接口与类之间继承例题
- 人证合一验证目前逐渐普及大众
- 织梦登陆总是提示验证码错误
- 用proteus实现STM32仿真
- linux 内核 mtd读取,linux内核 mtd分区
- 2023年全国最新交安安全员精选真题及答案4
- 户外风景拍摄自然风光摄影网站搭建模板
- 我的日本友人(二):清野先生
- 数商云采购管理系统方案助力采购平台:缩短采购周期、降本增效
- 知到网课艺术中国真题题库分享(含答案)
热门文章
- 【教程+源码】Java开发经典游戏飞翔的小鸟_Java游戏项目Flappy Bird像素鸟游戏
- 一月三万用户,我的迅载网盘运营经验
- Windows Server 2019 安装oracle11g
- 搜狗输入法如何java_java - 如何获取搜狗输入法的词库
- Typora 常用快捷键使用汇总
- mid是什么音乐文件?为什么这么小?
- 营销CRM软件(销售管理工具)让客户都成为回头客
- 6-4 结构体-查找最低分
- 国内优秀开源电商项目评测、PHP版和Java版都有开源
- 【BIOS大全】释义+设置+精解+释疑————玩转电脑必备工具帖(9)