使用@JsonIdentityInfo的Spring自定义序列化器

介绍

Spring中从JSON到JSON的序列化/反序列化已广泛用于基于Spring的现代应用程序中。 它基于杰克逊。 Jackson可以轻松地将任何POJO序列化为JSON,反之亦然。 这段代码写得很好。 我从未遇到任何问题。 当涉及到自定义序列化程序时,它将变得更加困难。 这篇文章展示了如何在带有自动装配字段的Spring中使用自定义序列化程序。

定义自定义序列化器

通常,自定义类的自定义序列化器继承自
com.fasterxml.jackson.databind.ser.std.StdSerializer。 此类定义了一些构造函数,但是框架只需要一个无参数的构造函数即可调用超类,如下所示:

public CustomSerializer() {this(null);
}public CustomSerializer(Class<ObjectToSerialize> t) {super(t);
}

然后是实际编写JSON必须实现的主要方法:

@Override
public void serialize(ObjectToSerialize value, JsonGenerator gen, SerializerProvider provider) throws IOException {gen.writeStartObject();...provider.defaultSerializeField("some field", value.getField(), gen);...gen.writeEndObject();
}

创建序列化程序类时,必须将其注册为ObjectToSerialize的序列化程序。 这可以通过在类上使用@JsonSerialize注释来完成:

@JsonSerialize(using = CustomSerializer.class)
public class ObjectToSerialize {

现在,杰克逊将对该类的所有实例使用此自定义序列化程序。 如有必要,可以通过子类编写自定义解串器
com.fasterxml.jackson.databind.deser.std.StdDeserializer <T>

循环引用和@JsonIdentityInfo

对于大多数使用Spring和Hibernate的商业应用,迟早会出现循环引用的问题。 这是一个简单的例子。

我们有2个课程:

public class Building {@Id@GeneratedValue(<parameters>)private Long id;private Set<Apartment> apartments;
}public class Apartment {@Id@GeneratedValue(<parameters>)private Long id;private Building building;
}

如果我们尝试序列化至少有一个公寓的建筑物,则会收到StackOverflowException。

杰克逊有一个解决此问题的方法-@JsonIdentityInfo。

如果将注释@JsonIdentityInfo添加到此类,则:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class ObjectToSerialize {

那么任何ObjectMapper都将通过用其ID替换除第一个对象以外的所有对象的出现而打破循环。 像这样:

{"id": 1,"apartments": [{"id": 2,"building": 1 - the object is replaced with its ID},{"id": 3,"building": 1 - the object is replaced with its ID}]
}

这些是Jackson提供的用于自定义序列化和处理循环引用的工具。

JSON结构问题

问题

@JsonIdentityInfo适用于简单的应用程序。 但是随着应用程序以默认格式增长,它可能会影响JSON的结构。 例如,如果某些方法在一个响应中返回建筑物和区域,则可能会发生以下情况:

{"buildings": [{"id": 1,"apartments": [{"id": 2,"building": 1 - the object is replaced with its ID},{"id": 3,"building": 1 - the object is replaced with its ID}]}],"districts": [{"buildings": [{"id": 5,...},1, - the object is replaced with its ID{"id": 6,...}]}]
}

从解析器的角度来看,这种替换可能非常不可预测。 在数组中,它可能会遇到对象和ID。 这可能发生在任何字段和任何对象上。 如果序列化提供程序多次发现该对象,则使用@JsonIdentityInfo对该类进行注释的任何对象都将替换为其ID。 序列化提供程序找到的具有相同ID的每个第二,第三,第四等实例都将替换为其ID。

这里的解决方案是使用单独的ObjectMapper编写JSON的一部分。 已经看到的ID的列表存储在由ObjectMapper创建的序列化提供程序中。 通过创建单独的ObjectMapper(具有可能不同的配置),可以重置列表。

对于返回不同对象类型的“复合” JSON结果,可以编写自定义序列化程序。 在此自定义序列化程序中,“标头”是使用JsonGenerator方法手动编写的,当达到JSON中的正确级别时,我们将创建一个新的ObjectMapper并编写外观更好的JSON。

{"buildings": [ - create a new ObjectMapper{"id": 1,"apartments": [{"id": 2,"building": 1 - the object is replaced with its ID},{"id": 3,"building": 1 - the object is replaced with its ID}]}],"districts": [ - create a new ObjectMapper{"buildings": [{"id": 5,...},{ - the object is written as a JSON Object not an ID"id": 1,...},{"id": 6,...}]}]
}

要将JSON写入原始生成器,我们可以使用
ObjectMapper.writeValueAsString和
JsonGenerator.writeRawValue(String)。

PS也可以通过以下方式创建新的序列化提供程序
DefaultSerializerProvider.createInstance(SerializationConfig,SerializerFactory),但它可能更复杂。

自定义序列化器自动装配问题

问题

我们希望能够在自定义序列化程序中使用@Autowire。 这是Spring的最佳功能之一! 实际上,如果使用默认的ObjectMapper,它就可以工作。 但是,如果我们使用JSON结构问题的解决方案,则该解决方案不适用于由我们自己的对象映射器实例化的自定义序列化程序。

我们自己的对象映射器必须配置有特殊的HandlerInstantiator:

// try to use the default configuration as much as possible
ObjectMapper om = Jackson2ObjectMapperBuilder.json().build();
// This instantiator will handle autowiring properties into the custom serializers
om.setHandlerInstantiator(
new SpringHandlerInstantiator(this.applicationContext.getAutowireCapableBeanFactory()));

如果自定义对象映射器是在另一个由默认ObjectMapper创建的自定义序列化器中创建的,则它可以自动装配ApplicationContext。

翻译自: https://www.javacodegeeks.com/2019/01/spring-custom-serializers-jsonidentityinfo.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/343889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【渝粤教育】电大中专电商运营实操 (15)作业 题库

1.目前菜鸟网络依赖大数据和云计算已实现了哪些功能&#xff08; &#xff09; A.智能分单 B.自动化仓库 C.以上都正确 D.智能发货 E.物流云加速 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;E 2.目前&#xff08; &#xff09;的电子商务呈现出巨大的发展潜力。 A…

java notify视频_一个很好的小例子来演示java中的wait()和notify()方法

任何人都可以在java中为我提供一个很好的小例子演示wait()和notify()功能.我尝试使用下面的代码,但它没有显示我的预期.public class WaitDemo {int i 10;int display() {System.out.println("Lexmark");i;return i;}}public class ClassDemo1 extends Thread {priv…

【渝粤教育】电大中专电子商务网站建设与维护 (22)作业 题库

1.阿里巴巴的创始人是&#xff08; &#xff09; A.丁磊 B.李彦宏 C.马化腾 D.马云 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;未作答 2.阿里巴巴目前的电子商务在哪个阶段&#xff08; &#xff09; A.资金流 B.物流 C.商品流 D.信息流 错误 正确答案&#xff1…

以太网交换机的用途有哪些?

交换机的主要功能包括物理编址、网络拓扑结构、错误校验、帧序列以及流控。交换机还具备了一些新的功能&#xff0c;如对VLAN&#xff08;虚拟局域网&#xff09;的支持、对链路汇聚的支持&#xff0c;甚至有的还具有防火墙的功能。接下来就由飞畅科技的小编带大家详细了解下交…

【渝粤教育】电大中专药理学基础 (3)作业 题库

1.关于巴比妥类药物药理作用的描述&#xff0c;错误的是&#xff08;&#xff09;。 A.镇静 B.催眠 C.麻醉 D.抗惊厥 E.镇痛 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;C 2.地西泮适应证不包括&#xff08;&#xff09;。 A.镇静催眠 B.抗癫痫和抗惊厥 C.肌紧张性…

交换机主要分为哪几类?

交换机&#xff08;Switch&#xff09;意为“开关”是一种用于电&#xff08;光&#xff09;信号转发的网络设备。它可以为接入交换机的任意两个网络节点提供独享的电信号通路。最常见的交换机是以太网交换机。其他常见的还有电话语音交换机、光纤交换机等。 从广义上来看&…

java编程彩球滑梯作弊_课内资源 - 基于C++的学生成绩管理系统

1 系统分析1.1 学生成绩管理系统介绍班主任管家软件以学生信息、课程信息为基础&#xff0c;以品行表现成绩(辅导员、班主任、班级评议成绩)和业务课程成绩为评价依据&#xff0c;每学期评定一次奖学金&#xff0c;奖学金作为学生评定各种荣誉的主要依据&#xff0c;并将各种评…

【渝粤教育】电大中专财务管理与分析 (2)作业 题库

货币市场的主要功能是调节短期资金融通&#xff0c;下列不属于货币市场的特点的是&#xff08; &#xff09;。 A期限一般长于1年 B期限短 C交易目的是解决短期资金周转 D金融工具有较强的“货币性” 正确 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2下列关于个人独…

Hibernate事实:如何“断言” SQL语句计数

介绍 Hibernate简化了CRUD操作&#xff0c;尤其是在处理实体图时。 但是任何抽象都有其代价&#xff0c;而Hibernate也不例外。 我已经讨论了获取策略和了解Criteria SQL查询的重要性&#xff0c;但是您可以做更多的事情来统治JPA。 这篇文章是关于控制Hibernate代表您调用SQL语…

交换机工作原理介绍

交换机是一种用于电&#xff08;光&#xff09;信号转发的网络设备。它可以为接入交换机的任意两个网络节点提供独享的电信号通路。最常见的交换机是以太网交换机。交换机工作于OSI参考模型的第二层&#xff0c;即数据链路层。交换机拥有一条高带宽的背部总线和内部交换矩阵&am…

【渝粤教育】电大中专金融与税收作业 题库

1.根据马克思的货币需要量公式&#xff0c;在货币流通速度不变的条件下&#xff0c;执行流通手段的货币量取决于&#xff08;&#xff09;。 A.商品质量 B.商品生产技术条件 C.待销售商品价格总额 D.投机性货币需求 错误 正确答案&#xff1a;左边查询 学生答案&#xff1a;A 2…

下载不了java应用程序_Java 7u45 - java webstart不会下载我的jar并执行应用程序,除非我显示java控制台...

首先&#xff0c;对不起我的英语&#xff0c;这不是我的母语。我的环境有&#xff1a;- jre 1.5.0_12(二进制)- jre 1.6.0_17(默认jre)- jre 1.7.0_45(二进制)我有两种方法可以通过Java Webstart启动应用程序&#xff1a;1)\\\javaws-1.5.0_12.exe \\\urClient-DAP2.jnlp2)&quo…

【渝粤题库】陕西师范大学500011 物理学史 作业(专升本)

《物理学史》作业 一、名词解释 1、伽利略“等末速度假设” 2、卡诺理想热机 3、光量子假设 4、阿拉果圆盘实验 5、活力守恒定律 6、牛顿主张的光的微粒说 7、卡诺提出的理想循环过程 8、法拉第圆盘实验 9、卡文迪许测量G的实验 10、卡诺定理 11、惠更斯原理 12、热质说 13、无…

将应用程序集成为Heroku附加组件

Heroku是受欢迎的平台即服务提供商&#xff0c;它为供应商提供了作为附件提供的选项。 Heroku客户可以以不同的方式使用加载项&#xff0c;但是典型的情况是“启动数据库”&#xff0c;“启动MQ”或“启动日志记录解决方案”。 将附加组件添加到您的帐户后&#xff0c;您可以连…

bitmap的java原理_布隆算法的原理及JAVA实现

Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法。通常应用在一些需要快速判断某个元素是否属于集合&#xff0c;但是并不严格要求100%正确的场合。Bloom Filter是一种空间效率很高的随机数据结构&#xff0c;它利用位数组很简洁地表示一个集合&#xff…

[渝粤教育] 中国地质大学 自动控制原理 复习题

《自动控制原理》模拟题 一.单选题 1.当输入为单位斜坡且系统为单位反馈时对于II型系统其稳态误差为() A.0 B.0.1/k C.1/k D.无穷大 2.I型系统开环对数幅频特性的低频段斜率为() A.-40(dB/dec) B.-20(dB/dec) C.0(dB/dec) D.20(dB/dec) 3.当输入为单位斜坡且系统为单位反馈时…

什么是语音复用设备?

语音复用设备是一种小容量、多业务的复用及传输设备&#xff0c;它能为用户提供综合的通信功能&#xff0c;满足用户对电话、数据以及计算机网络连接的实际需要。它的多种传输方式使其能灵活的应用在各种通信网络中&#xff1a;可以作为光电一体化综合通信业务接入设备&#xf…

[渝粤教育] 中国地质大学 金融保险业会计 复习题 (2)

《金融保险会计》模拟题 单选题 1.下列不符合外汇分账制基本要求的有(). A.对各种外币的收付凡有人民币牌价的平时都按原币填制凭证登记账簿编制报表 B.对各种外币的收付凡有人民币牌价的平时都按人民币填制凭证登记账簿编制报表 C.设置”外汇买卖”科目 D.各种外币分别设置一…

截断整型提升算数转换

文章目录 &#x1f680;前言&#x1f680;截断&#x1f680;整型提升✈️整型提升是怎样的 &#x1f680;算术转换 &#x1f680;前言 大家好啊&#xff01;这里阿辉补一下前面操作符遗漏的地方——截断、整型提升和算数转换 看这一篇要先会前面阿辉讲的数据的存储否则可能看不…

java如何通过grpc连接etcd_grpc通过 etcd 实现服务发现与注册-源码分析

介绍下面介绍 jupiter-0.2.7 版本中 grpc 通过 etcd 实现服务发现与注册。服务发现与注册的实现解析服务注册服务注册的流程图&#xff1a;etcd的服务注册代码模块在 jupiter/pkg/registry/etcdv3 中。下面让我们来看看实际的代码// Registry register/unregister service// re…