fastjson list转json字符串_从fastjson转jackson的血泪史
示例用法:// fastjson 序列化JSON.toJSONString(javaObj, SerializerFeature.WriteClassName);// 类似这样{"@type":"java.util.HashMap","data":{"@type":"...// fastjson 反序列化ParserConfig config = new ParserConfig() ;config.setAutoTypeSupport(true);Map map = JSON.parseObject(json, Map.class, config);
使用相同的特性。在 jackson 框架下,发现性能依然贼好!!最终决定,全面更换 jackson。由于使用json的地方特别多。大致的更换方案是,完全重写 fastjson 相关的类。尽可能少改动项目现有代码。像 fastjson 中的 JSON, JSONObject, JSONArray 都保持原包名和 类名重写相关使用的方法。重写完后,以为大功告成,去掉 fastjson的依赖,以为可以上线了!!万万没有想到,这只是万里长征的第一步!!也让我深深体会到 fastjson 的兼容性是有多么多么的好。各种神操作,让你在 jackson 中,都不知道如何改写。也怪我们使用 fastjson的方式太邪乎了!各种非常规使用。下面讲几个特殊的解析:
javabean的属性是String, 反序列化时,传入这个属性的值是json对象或者json 数组;
属性是枚举,传入 json 对象;
属性是对象,传入是String,String是一个json串;
属性是集合,传入是单个json对象;jackson有配置可以使用configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)解决问题,但是这样影响处理属性是集合类型,而传入是String的问题。我就没有使用该特性。然后在自定义异常处理中统一处理该问题
// 问题示例描述public class Abc{ private String attrArr;// 问题1 传入json数组[{"a":"123123"}] private String attr;// 问题1 传入json对象{"a":"123123"} private SexEnum sexEnum;// 问题2 传入json对象{"value":1,"label":"男"} private BBB bbb; // 问题3 传入字符串"{\"b\":\"abc\"}" private List bbb; // 问题4 传入json对象{"b":"abc"} // ...get/set...方法 }public class BBB{ private String b; // ... get/set...方法 } 在fastjson 中是都可以正常转化
以上举例的反序列化在jackson中直接报错,在网上未能找到相应问题的解决办法,但是最终通过跟踪报错的堆栈信息,进行调试后,发现可以添加一个异常处理的方法。解决这4个问题代码如下:
// 对应jackson 的版本 2.11.3, 早期版本可能没有该方法或者参数列表不一致objectMapper.addHandler(new CustomDeserializationProblemHandler());static class CustomDeserializationProblemHandler extends DeserializationProblemHandler { @Override public Object handleUnexpectedToken(DeserializationContext ctxt, JavaType targetType, JsonToken t, JsonParser p, String failureMsg) throws IOException { String json = p.getText(); if(targetType.isEnumType() && "{".equals(json)) { ObjectMapper mapper = (ObjectMapper) p.getCodec(); mapper.readTree(p);// 直接读取一个节点。这样就不会忽略之后的结点解析了,但是并不能正确反序列化枚举,需要通过注解实现 return null; } if(targetType.isCollectionLikeType() && "{".equals(json)) { ObjectMapper mapper = (ObjectMapper) p.getCodec(); Object obj = mapper.readValue(p, targetType.getContentType());// 把单个结点数据,转化为一个数组对象 List<Object> list = new ArrayList<Object>(); list.add(obj); return list; } if(targetType.getRawClass().equals(String.class) && "{".equals(json)) { ObjectMapper mapper = (ObjectMapper) p.getCodec(); TreeNode node = mapper.readTree(p);// 把一个对象json,转成一个字符串,有性能损失 return node.toString(); } if(targetType.getRawClass().equals(String.class) && "[".equals(json)) { ObjectMapper mapper = (ObjectMapper) p.getCodec(); TreeNode node = mapper.readTree(p);// 把一个对象json数组,转成一个字符串,有性能损失 return node.toString(); } if ((json.startsWith("{") && json.endsWith("}")) || (json.startsWith("[") && json.endsWith("]"))) { return JSON.parseObject(p.getText(), targetType); } return DeserializationProblemHandler.NOT_HANDLED; } }
日期类型反序列化支持多种格式;
在 fastjson 中,长整型、yyyy-MM-dd、yyyy-MM-dd HH:mm 等格式都能正确转化为日期。但是在 jackson 中默认长整型是可以正常转换的。但是另外两种并不能转换,解决办法如下:SimpleModule serializerModule = new SimpleModule("DateSerializer", PackageVersion.VERSION); serializerModule.addDeserializer(Date.class, new CustomDateDeSerializer()); objectMapper.registerModule(serializerModule);static class CustomDateDeSerializer extends DateDeserializers.DateDeserializer { private static final long serialVersionUID = 1L; @Override public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p != null) { String calendatStr = p.getText(); if (calendatStr != null && calendatStr.indexOf("T") < 0 && calendatStr.length() == 19) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { return sdf.parse(calendatStr); } catch (ParseException e) { } } if (calendatStr != null && calendatStr.indexOf("T") < 0 && calendatStr.length() == 16) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); try { return sdf.parse(calendatStr); } catch (ParseException e) { } } if (calendatStr != null && calendatStr.length() == 10 && calendatStr.charAt(4) == '-' && calendatStr.charAt(7) == '-') { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); try { return sdf.parse(calendatStr); } catch (ParseException e) { } } } return super.deserialize(p, ctxt); } }
jackson最新版本中做类型保留,这样配置;
// jackson 2.11.3 配置该信息后,序列化和反序列化都会带有类信息objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
枚举类型序列化是以类(即输出属性)形式输出;
// 在枚举上添加该注解@JsonFormat(shape = Shape.OBJECT)public enum SexEnum{ ..... }
最后分享一下关于JSON使用的愚见
1)如果项目中在使用 fastjson 但是没有使用SerializerFeature.WriteClassName特性,没有必要更换新的json 库。但是建议升级最新版本。因为不久前报过多次严重的安全漏洞。
2)保留类信息的方式,反序列化可能成为黑客攻击的入口。该种方式仅用于项目内部接口的调用。
3)应规范使用json 的序列化和反序列化。上边提到的第1点。不管在 fastjson还是上边提到的 jackson 解决方案都影响性能。
4)对于{"action":"add","data":{...大量信息....}}这样json想先确认action值,再对 data做相应类型的解析,建议新建一个类似class SimpleCommand{String action;...get/set...}这样只有 action 一个属性的类进行解析,然后根据 action 值再进行整个json的解析。速度更快一些。
(全文完)
↓↓↓推荐↓↓↓
一码解千愁
fastjson list转json字符串_从fastjson转jackson的血泪史相关推荐
- fastjson list转json字符串_程序员:JSON、JSONObject 与 JSONArray 简单讲解
fastjson简介 fastjson 是阿里巴巴的开源JSON解析库,它可以解析 JSON 格式的字符串,支持将 Java Bean 序列化为 JSON 字符串,也可以从 JSON 字符串反序列化到 ...
- fastjson解析多层Json字符串
Json字符串: {"status":0,"result":{"location":{"lng":120.3252155 ...
- java处理json字符串_常见java对象转换为json字符串处理!!!
1.JSON简介 1. 概念: JavaScript Object NotationJavaScript对象表示法 Person p = new Person(); p.setName("张 ...
- java中转json字符串_如何在Java中转义JSON字符串-Eclipse IDE技巧
java中转json字符串 在Java应用程序中工作或进行JSON解析时,通常很常见的做法是从某些资源(例如RESTful Web服务)中复制粘贴JSON字符串,然后使用Jackson库解析JSON. ...
- android jackson 解析json字符串,一文搞定Jackson解析JSON数据
Json解析-Jackson使用教程 日常求赞,感谢老板. 一.JSON解析 我这里指的解析是:JSON和JavaObject之间的序列化和反序列化. 如果你的项目进行了前后端分离,那你一定使用过JS ...
- json字符串与java对象的相互转换(jackson)
1.java对象转换为json字符串 package com.chichung.json;import com.fasterxml.jackson.core.JsonProcessingExcepti ...
- 使用fastjson工具类json字符串和对象之间的转换
文章目录 一.引入依赖 二.创建user实体类 三.测试 一.引入依赖 <!--字符串和对象操作工具类 Start--><dependency><groupId>c ...
- java json 内部类_使用Fastjson解析内部类的一个小问题
使用的Fastjson的版本是1.2.7和1.2.47两个版本. 1. 问题 使用Fastjson解析包含内部类的对象时,发生异常,代码大致如下: public class HelloControll ...
- Fastjson使用:将json字符串转对象为空问题
问题背景 在一次更改老项目中,因为想使用构造器方便点,就在原来的代码基础上增加了一个有参构造器,原来的代码是没有设置构造器的.(没有设置的话使用默认的一个无参构造器) . 然后因为我新创建的有参构造器 ...
最新文章
- 字节跳动_掌握Java字节码
- Springmvc与Struts2不同
- c++作业5 9.22
- python中cgi到底是什么_什么是CGI?详细介绍Python CGI编程
- DLL入门浅析(4)——从DLL中导出类
- JAVA学习笔记--初识容器类库
- zabbix监控MogDB之采集prometheus数据
- (88)FPGA乘法器设计(移位相加乘法器)
- 拳王虚拟项目公社:知识付费之出售虚拟教程资源赚钱,小白轻松赚钱的方式
- Django项目实践3 - Django模型(view-数据库)
- mask rcnn数据转换为tfrecord数据
- 二维码解析易语言代码
- ubuntu翻译软件安装
- 织梦后台登录出现500错误解决方案
- 你对Web3的迅速发展一无所知,逃离大厂去拥抱Web3
- 骚操作之Python微信远程控制摄像头!然后嘿嘿嘿!
- Windflowers(歌词)
- 网页集成大华摄像头以及回放功能2019.11.14
- 学计算机会学dos,DOS操作系统和上课学习的应用软件_CPUCPU评测-中关村在线
- GObject对象系统