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

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

spring序列化

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

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

相关文章

阐述计算机网络的作用答案,计算机网络习题及答案(50页)-原创力文档

计算机网络习题及答案第一章 计算机网络的基本概念一、选择题√1、完成路径选择功能是在 OSI 模型的( )。A.物理层 B.数据链路层 C. 网络层 D.运输层2、在 TCP/IP 协议簇的层次中&#xff0c;保证端-端的可靠性是在哪层上完成的&#xff1f;()A. 网络接口层 B.互连层 C.传输层 …

python func_Python functool module

1.functools.partial(func,*args,**keywords) 实现 def partial(func, *args, **keywords):def newfunc(*fargs, **fkeywords): newkeywordskeywords.copy() newkeywords.update(fkeywords)return func(*args, *fargs, **newkeywords) newfunc.funcfunc newfunc.argsargs newfu…

IntelliJ IDEA for Mac中的Maven操作窗口详解

文章目录简介操作按钮详解Reload All Maven ProjectsGenerate Sources and Update Folders For All ProjectsDownload Sources and/or DocumentationAdd Maven ProjectsRun Maven BuildExecute Maven GoalToggle Offline ModeToggle Skip Tests ModeShow Dependencies布局展示模…

java 验证码透明背景_Java中的证书透明度验证

java 验证码透明背景因此&#xff0c;我有一个幼稚的想法&#xff0c;即除了证书有效性检查&#xff08;在Java中&#xff09;之外&#xff0c;将证书透明性验证作为每个请求的一部分也很容易。 牺牲了整个周末的一半时间&#xff0c;我可以证明这并不是一件小事。 但是&#…

html ajax请求jsp,JSP+jquery使用ajax方式调用json的实现方法

本文实例讲述了JSPjQuery使用Ajax方式调用JSON的实现方法&#xff0c;在这里分享给大家以供大家参考&#xff0c;具体的实现以及代码如下所示&#xff1a;前台&#xff1a;//testfunction test(uid){if(confirm("确定该用户操作"uid"吗&#xff1f;")){var…

ai背景合成_智能合成AI主播很危险,应立即取消!

邱震海分享我对时政问题的看法点击↑↑↑音频收听“倾听彼得 邱”音频背景每年两会&#xff0c;关注报道两会的记者多达3000多人&#xff0c;他们分布在会场内外及时捕捉两会动人瞬间和重要时刻&#xff0c;及时向全国乃至全球读者传递。但是今年的两会报道期间&#xff0c;新…

spring注入私有字段_Spring字段依赖注入示例

spring注入私有字段了解如何编写Spring Field Injection示例 。 字段注入是Spring框架 依赖注入的一种 。 在本教程中&#xff0c;我们将编写几个类&#xff0c;并看一看现场注入工程。 有关Spring依赖注入的更多信息&#xff1a; Spring Setter依赖注入示例 Spring构造函数…

简述html的3种列表uloldl,语义化HTML:ul、ol和dl

一、语义化元素1. ul标签W3C草案&#xff1a;The ul element represents an unordered list of items; that is, a list in which changing the order of the items would not change the meaning of list.语义化元素&#xff1a;表示包含一组无序列表项内容。在不同的浏览器默…

centos8 kernel source 安装_什么?你在物理机上安装Oracle总失败?那就试试Docker吧

写在前面有些小伙伴按照我写的《【Oracle】什么&#xff1f;作为DBA&#xff0c;你竟然不会安装Oracle&#xff1f;&#xff1f;》一文&#xff0c;在CentOS 8.0服务器上来安装Oracle&#xff0c;总是说&#xff1a;安装不成功&#xff01;但是我确实也是在CentOS 8.0服务器上安…

Maven的资源坐标

在 Maven 中&#xff0c;坐标是资源包的唯一标识&#xff0c;Maven 通过坐标在仓库中找到唯一的资源。 下面就是 javax.servlet-api-4.0.1.jar 的坐标&#xff1a; <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</…

starter_您是否尝试过MicroProfile Starter?

starterhttps://start.spring.io的SPRING INITIALIZR已经存在了一段时间&#xff0c;并且是引导新的Spring Boot应用程序的最佳方法。 到目前为止&#xff0c;即使不同的供应商为其实施提供了启动器&#xff0c;也没有类似的方式来引导新的MicroProfile项目。 但是等待已经结束…

html2image乱码问题,HtmlImageGenerator字体乱码问题解决、html2image放linux上乱码问题解决...

使用html2image-0.9.jar生成图片。在本地window系统正常&#xff0c;放到服务器linux系统时候中文乱码问题。英文可以&#xff0c;中文乱码应该就是字体问题了。一、首先需要在linux安装字体&#xff0c;simsun.ttc simsun.ttf simsunb.ttf1、新建目录/user/share/fonts/chine…

java每个阶段的学习时间_每个Java学习者都会犯的10个最常见的1个错误

java每个阶段的学习时间据说&#xff1a;“您的朋友会吞下您的错误&#xff0c;您的敌人会将它们呈现在盘子上”。 我绝对不是你的敌人&#xff0c;但我想向您介绍一些针对每个Java初学者的错误&#xff0c;我将在此博客“标牌”上就此做错。 当然只有其中一些&#xff0c;我是…

高速信号传输约翰逊 pdf_高速数字电路仿真设计与测试技术发展趋势综述 (一)...

近十多年来&#xff0c;数字集成电路和各种接口总线标准的发展令人眼花缭乱&#xff0c;目不暇接。各个总线标准通常由不同团队制订&#xff0c;其纷繁芜杂的测试和测量技术给从业人员带来许多困扰。本文将就当下的一些主要接口总线标准的仿真设计与测试技术发展趋势作一些简明…

Maven的继承

文章目录什么是继承&#xff1f;如何实现继承&#xff1f;什么是继承&#xff1f; 在聚合多个项目时&#xff0c;如果这些被聚合的项目中需要引入相同的Jar&#xff0c;那么可以将这些Jar写入父pom中&#xff0c;各个子项目继承该pom即可。 如何实现继承&#xff1f; 父pom配…

八中计算机是学啥的,北京八中:居然有这么好玩的课

北京八中&#xff1a;居然有这么好玩的课中国青年报北京12月13日电(记者堵力)种种“稀奇古怪”的科技知识纳入了北京八中学生们的正式课程。每周&#xff0c;所有的学生都会面对各种仪器&#xff0c;学习电台、电脑&#xff0c;以及兵器装备的知识等等———12月13日上午9&…

@builder注解_SpringBoot 整合SpringSecurity示例实现前后分离权限注解+JWT登录认证

一.说明SpringSecurity是一个用于Java 企业级应用程序的安全框架,主要包含用户认证和用户授权两个方面.相比较Shiro而言,Security功能更加的强大,它可以很容易地扩展以满足更多安全控制方面的需求,但也相对它的学习成本会更高,两种框架各有利弊.实际开发中还是要根据业务和项目…

web前端面试问答_Web服务面试问答

web前端面试问答在这篇文章中&#xff0c;我们涵盖了您需要熟悉的Web服务概念的几乎所有部分&#xff0c;以回答任何层级问题。 您还将在分类中找到最佳的Web服务面试问题和答案&#xff0c;因此只有在必要时才可以使用特定条款。 今天可以在各种编程平台上开发各种Web应用程序…

Maven项目的pom.xml文件详解

文章目录pom.xml文件解读标签 dependency 的解读pom.xml文件解读 <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0http://maven.…