Jackson中的自定义反序列化器和验证

tl; dr:将输入验证添加到Jackson中的自定义json解串器很重要。

在RHQ中,我们在几个地方使用了Json解析-直接在as7 / Wildfly插件中,或者通过RESTEasy 2.3.5间接在REST-api中使用,已经很繁重了。

现在,我们有一个bean Link ,看起来像:

public class Link {String rel;String href;
}

序列化的标准方法是

{ "rel":"edit", "href":"http://acme.org" }

由于我们需要其他格式,因此我编写了一个自定义序列化程序并将其附加到类上。

@JsonSerialize(using = LinkSerializer.class)
@JsonDeserialize(using = LinkDeserializer.class)
@Produces({"application/json","application/xml"})
public class Link {private String rel;private String href;

此自定义格式如下:

{"edit": {"href": "http://acme.org"}
}

由于客户端也可以发送链接,因此需要进行一些自定义反序列化。 解串器的第一个片段看起来像这样,效果很好:

public class LinkDeserializer extends JsonDeserializer>{@Overridepublic Link deserialize(JsonParser jp,DeserializationContext ctxt) throws IOException{String tmp = jp.getText(); // {jp.nextToken(); // skip over { to the relString rel = jp.getText();jp.nextToken(); // skip over  {[…]Link link = new Link(rel,href);return link;}

现在,几天前发生的事情是,在某些测试中,我正在发送数据,而我们的服务器严重崩溃。 内存使用量增加,垃圾收集器花费了大量cpu时间,并且该调用最终因OutOfMemoryException终止。

经过一番调查,我发现客户端不是以我们的特殊格式发送Link对象,而是以我最初显示的原始格式发送。 进一步的研究表明,实际上, LinkDeserializer正在消耗流中的令牌,如上所示,然后还吞没了输入中的后续令牌。 因此,当它返回时,整个解析器的状态很差,然后尝试复制大数组,直到我们看到OOME。

得到这个之后,我更改了实现以添加验证并在无效输入时尽早提供援助,以使解析器在无效输入时不会陷入不良状态:

public Link deserialize(JsonParser jp,DeserializationContext ctxt) throws IOException{String tmp = jp.getText(); // {validate(jp, tmp,"{");jp.nextToken(); // skip over { to the relString rel = jp.getText();validateText(jp, rel);jp.nextToken(); // skip over  {tmp = jp.getText();validate(jp, tmp,"{");[…]

然后,那些validate*()简单地将令牌与传递的期望值进行比较,并对意外输入抛出Exception:

private void validate(JsonParser jsonParser, String input,String expected) throws JsonProcessingException {if (!input.equals(expected)) {throw new JsonParseException("Unexpected token: " + input,jsonParser.getTokenLocation());}}

验证也许可以进一步改进,但是您可以理解。

参考: Jackson中的Custom Deserializer,以及 JCG合作伙伴 Heiko Rupp在“ 一些要记住的博客”上的验证。

翻译自: https://www.javacodegeeks.com/2013/08/custom-deserializer-in-jackson-and-validation.html

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

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

相关文章

java ssh shell命令_java 通过ssh 执行命令

java 里面的开源 ssh libjsch 例子JSch jSch new JSch();//设置JSch 的日志,可以看到具体日志信息JSch.setLogger(new Logger() {Overridepublic boolean isEnabled(int level) {return true;}Overridepublic void log(int level, String message) {System.out.pri…

标准易语言学习

1、窗口程序加入自定义局部变量 按CTRLL弹出局部变量表(或点菜单栏上的插入,选择局部变量)转载于:https://www.cnblogs.com/slyzly/articles/9048724.html

c# TCP高性能通信

开篇都是吹牛逼哈。。。 我原本打算使用dotnetty来解决传输问题,但是试了下没有成功,也没有找到相关问题解决方法,导出源码,好大啊。暂时不想研究,而且是.Net Core的。最后没有办法,就自己封装了。我就不上…

vue项目中keep-alive的使用,从详情页返回列表时保存浏览位置

背景描述: 最近在做移动端前端项目中,需要实现以下场景: 1.在页面查询列表,进入详情页时,返回需要页面返回到上次浏览的位置 2.由于查询列表获取的数据可能会短时间改变,如果前端长时间缓存数据&#xf…

Apache log4j是领先的日志记录框架

根据 从零周转开始的调查中, Apache log4j是领先的Java日志记录框架。 这实际上是一个非常有趣的调查。 它显示SLF4J最常用作伐木外墙,占61%。 但是,它似乎最常与Apache Log4j一起使用,52%的调查参与者都…

Centos6.8通过yum安装mysql5.7

Centos6.8通过yum安装mysql5.7 2017年07月13日 14:19:10 阅读数:1067 1.安装mysql的yum源 a.下载配置mysql的yum源的rpm包 根据上面3张图片中的操作下载下来的rpm文件可以通过如下命令获取: wget https://dev.mysql.com/get/mysql57-community-release-e…

codeforces Labyrinth

codeforces Labyrinth Time Limit: 2 Sec   Memory Limit: 512 MB Description You are playing some computer game. One of its levels puts you in a maze consisting of n lines, each of which contains m cells. Each cell either is free or is occupied by an obstac…

在vscode使用editorconfig的正确姿势

editorconfig是什么鬼? editorconfig是用来帮助开发者定义和维护代码风格(行尾结束符、缩进风格等)的东东。 editorconfig支持哪些规则? 请自行参考 https://editorconfig.org/ 如何在vscode中使用editorconfig? 在…

使用Java的Apache Camel入门

Apache Camel是一个非常有用的库,可以帮助您处理来自许多不同来源的事件或消息。 您可以通过许多不同的协议(例如在VM,HTTP,FTP,JMS甚至DIRECTORY / FILE之间)移动这些消息,但仍使处理代码不受传…

Mvc+Hui+SqlSugar+Autofac+NLog+T4 架构设计(一)

一、前言 作为小菜鸟第一次写博客的我还有点小激动,最近开始打算着手写一个属于自己架构。算下来差不多最近花一周多的下班时间了来写这个框架,本来想整体架构开发完成测试完成后才写博客,怕自己没时间或失去动力,就先把自己架构设…

闲话杂谈—至曾经的自己

【这篇闲话杂谈写的背景时间是:2018年9月30号】 今天估计是自己突然灵光一闪,又或许是想到昨天团建时曾经带自己的师傅(刘工)的一番话。让我觉得大家都在变化,都慢慢的不再是曾经咱们一块儿奋斗、一块儿无话不谈&#…

房价在手,天下我有 --反手就撸一个爬虫(终)

接上篇,科科,好,我们继续 我们在这里先把json数据入库吧~ 首先,database/scheme里定义好数据类型。 const mongoose require(mongoose)const detailHouseSchema new mongoose.Schema({ //定义数据模式link:String…

1.1 计算机网络的形成和发展

1.早期计算机网络:20世纪60年代前 计算机和通信技术结合的先驱:SAGE半自动化地面防空系统 ,该系统由麻省理工学院林肯实验室设计。 计算机通信在民用领域的代表:飞机订票系统SABRE-I ,美国航空公司与IBM公司联合开发。…

Spring MVC:带有CNVR卷的REST应用程序。 1个

不久前,我阅读了Paul Chapman撰写的有关内容协商视图解析器 (CNVR)的文章。 Spring Framework Blog上的那篇文章启发了我研究这个框架的领域。 因此,我开发了一个基于Spring MVC和CNVR的 REST示例应用程序。 该应用程序演示了REST…

《精通Spring 4.x 企业应用开发实战》学习笔记

第四章 IoC容器 4.1 IoC概述 IoC(Inverse of Control 控制反转),控制是指接口实现类的选择控制权,反转是指这种选择控制权从调用类转移到外部第三方类或容器的手中。 也就是由Spring容器借由Bean配置来进行控制。 DI(D…

微前端——无界wujie

B站课程视频 课程视频 课程课件笔记: 1.微前端 2.无界 现有的微前端框架:iframe、qiankun、Micro-app(京东)、EMP(百度)、无届 前置 初始化 新建一个文件夹 1.通过npm i typescript -g安装ts 2.然后可…

java executor spring_Spring+TaskExecutor实例

一 TaskExecutor接口Spring的TaskExecutor接口等同于Java.util.concurrent.Executor接口。 实际上,它存在的主要原因是为了在使用线程池的时候,将对Java 5的依赖抽象出来。 这个接口只有一个方法execute(Runnable task),它根据线程池的语义和…

小程序居然可以用WXS模拟实现过滤器!

小程序目前官方还没有出过滤器,特别不方便,但是可以用wxs来模拟过滤器,话不多说,直接上代码。当然,不熟悉wxs的可以先看一下 官方文档 1.新建一个filter.wxs的文件我个人建议是一个过滤器写一个wxs,避免引用…

ADF:使用HTTP POST方法进行URL任务流调用

众所周知,可以通过某些URL直接从浏览器或某些外部应用程序调用有限任务流。 如果任务流的属性“ URL invoke”设置为“ url-invoke-allowed”,则启用此功能,该功能通常在集成项目中使用。 通常,客户端(或调用者&#x…

(十二)Bind读取配置到C#实例

继续上一节的,接下来用Options或者Bind把json文件里的配置转成C#的实体,相互之间映射起来。首先新建一个asp.net core mvc项目OptionsBindSampleStartup.cs,这里用依赖注入把Configuration加进来 1 public IConfiguration Configurat…