0x00 前言

在工作开发总,有一个需求需要将项目中的fastjson迁移至gson,在迁移过程中发现了一个奇葩的bug,如下:

org.springframework.http.converter.HttpMessageNotWritableException:
Could not write JSON: (was java.lang.IllegalStateException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.IllegalStateException) (through reference chain: com.demo.boot.web.common.RestWebResultContainer["data"]->com.google.gson.JsonArray["asInt"])
0x01 问题分析

看到第一眼知道是反序列化失败,但是用fastjson的JSONArray就没问题,为啥换成gson的的JsonArray就有这个问题了呢,后续通过对于两者的源码分析看出。

fastjson中的JSONArray


package com.alibaba.fastjson;import com.alibaba.fastjson.JSONObject.SecureObjectInputStream;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.TypeUtils;
import java.io.IOException;
import java.io.NotActiveException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.RandomAccess;public class JSONArray extends JSON implements List<Object>, Cloneable, RandomAccess, Serializable {private static final long serialVersionUID = 1L;private final List<Object> list;protected transient Object relatedArray;protected transient Type componentType;.......public Object get(int index) {return this.list.get(index);}public JSONObject getJSONObject(int index) {Object value = this.list.get(index);if (value instanceof JSONObject) {return (JSONObject)value;} else {return value instanceof Map ? new JSONObject((Map)value) : (JSONObject)toJSON(value);}}public JSONArray getJSONArray(int index) {Object value = this.list.get(index);if (value instanceof JSONArray) {return (JSONArray)value;} else {return value instanceof List ? new JSONArray((List)value) : (JSONArray)toJSON(value);}}public <T> T getObject(int index, Class<T> clazz) {Object obj = this.list.get(index);return TypeUtils.castToJavaBean(obj, clazz);}public <T> T getObject(int index, Type type) {Object obj = this.list.get(index);if (type instanceof Class) {return TypeUtils.castToJavaBean(obj, (Class)type);} else {String json = JSON.toJSONString(obj);return JSON.parseObject(json, type, new Feature[0]);}}public Boolean getBoolean(int index) {Object value = this.get(index);return value == null ? null : TypeUtils.castToBoolean(value);}public boolean getBooleanValue(int index) {Object value = this.get(index);return value == null ? false : TypeUtils.castToBoolean(value);}public Byte getByte(int index) {Object value = this.get(index);return TypeUtils.castToByte(value);}public byte getByteValue(int index) {Object value = this.get(index);Byte byteVal = TypeUtils.castToByte(value);return byteVal == null ? 0 : byteVal;}public Short getShort(int index) {Object value = this.get(index);return TypeUtils.castToShort(value);}public short getShortValue(int index) {Object value = this.get(index);Short shortVal = TypeUtils.castToShort(value);return shortVal == null ? 0 : shortVal;}public Integer getInteger(int index) {Object value = this.get(index);return TypeUtils.castToInt(value);}public int getIntValue(int index) {Object value = this.get(index);Integer intVal = TypeUtils.castToInt(value);return intVal == null ? 0 : intVal;}public Long getLong(int index) {Object value = this.get(index);return TypeUtils.castToLong(value);}public long getLongValue(int index) {Object value = this.get(index);Long longVal = TypeUtils.castToLong(value);return longVal == null ? 0L : longVal;}public Float getFloat(int index) {Object value = this.get(index);return TypeUtils.castToFloat(value);}public float getFloatValue(int index) {Object value = this.get(index);Float floatValue = TypeUtils.castToFloat(value);return floatValue == null ? 0.0F : floatValue;}public Double getDouble(int index) {Object value = this.get(index);return TypeUtils.castToDouble(value);}public double getDoubleValue(int index) {Object value = this.get(index);Double doubleValue = TypeUtils.castToDouble(value);return doubleValue == null ? 0.0D : doubleValue;}public BigDecimal getBigDecimal(int index) {Object value = this.get(index);return TypeUtils.castToBigDecimal(value);}public BigInteger getBigInteger(int index) {Object value = this.get(index);return TypeUtils.castToBigInteger(value);}public String getString(int index) {Object value = this.get(index);return TypeUtils.castToString(value);}public Date getDate(int index) {Object value = this.get(index);return TypeUtils.castToDate(value);}public java.sql.Date getSqlDate(int index) {Object value = this.get(index);return TypeUtils.castToSqlDate(value);}public Timestamp getTimestamp(int index) {Object value = this.get(index);return TypeUtils.castToTimestamp(value);}.........
}

gson中的JsonArray

package com.google.gson;import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public final class JsonArray extends JsonElement implements Iterable<JsonElement> {private final List<JsonElement> elements;......public Number getAsNumber() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsNumber();} else {throw new IllegalStateException();}}public String getAsString() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsString();} else {throw new IllegalStateException();}}public double getAsDouble() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsDouble();} else {throw new IllegalStateException();}}public BigDecimal getAsBigDecimal() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsBigDecimal();} else {throw new IllegalStateException();}}public BigInteger getAsBigInteger() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsBigInteger();} else {throw new IllegalStateException();}}public float getAsFloat() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsFloat();} else {throw new IllegalStateException();}}public long getAsLong() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsLong();} else {throw new IllegalStateException();}}public int getAsInt() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsInt();} else {throw new IllegalStateException();}}public byte getAsByte() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsByte();} else {throw new IllegalStateException();}}public char getAsCharacter() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsCharacter();} else {throw new IllegalStateException();}}public short getAsShort() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsShort();} else {throw new IllegalStateException();}}public boolean getAsBoolean() {if (this.elements.size() == 1) {return ((JsonElement)this.elements.get(0)).getAsBoolean();} else {throw new IllegalStateException();}}........
}

通过对比可以看出JsonArray中有大量的get方法且无参,这样会导致将JsonArray作为序列化对象传输后在对其进行反序列化后会将例如getAsInt转化成asInt属性,这样找不到会报错,上述错误是找不到asInt的set方法,所以出现类似错误时可以看看对应类型的getter/setter方法有没有写,并且类型时候对应。

0x02 问题解决

找到错误原因后果断放弃将JsonArray作为回传对象,采用List回传 ,接口数据返回正常。

 JsonArray jsonArray = xxx;return Arrays.asList(new Gson().fromJson(jsonArray, Dto[].class));
0x03 总结

有问题不要乱尝试,要学会分析,不要猜,和女人的心思一样,特别难猜到!!!!

经过此次折磨的BUG , 个人觉得fastjson更合适作为一个对象,而gson更像是一个工具类。

问题解决:fastjson 迁移至gson 反序列化错误,看这篇就够!相关推荐

  1. 大型项目废弃fastjson迁移至Gson保姆级攻略

    前言 大家好,又双叒叕见面了,我是天天放大家鸽子的蛮三刀. 在被大家取关之前,我立下一个"远大的理想",一定要在这周更新文章.现在看来,flag有用了... 本篇文章是我这一个多月 ...

  2. .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了

    本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新手朋友),但是转念一想不如来点猛的(考虑到急性子的朋友),让你通过本文的学习就能快速的入门ASP.NET Core.既 ...

  3. Docker入门实战看这篇就够了(最新详细以及踩过的坑)

    Docker入门实战看这篇就够了 前言 初识 是什么 容器与虚拟机 能干什么 去哪玩 安装 先决条件 查看自己的内核 安装所需的软件包(支持devicemapper存储类型) 设置镜像的仓库 设置yu ...

  4. [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了

    园子里关于ASP.NET Core Web API的教程很多,但大多都是使用EF+Mysql或者EF+MSSQL的文章.甚至关于ASP.NET Core Web API中使用Dapper+Mysql组 ...

  5. 史上最全!用Pandas读取CSV,看这篇就够了

    导读:pandas.read_csv接口用于读取CSV格式的数据文件,由于CSV文件使用非常频繁,功能强大,参数众多,因此在这里专门做详细介绍. 作者:李庆辉 来源:大数据DT(ID:hzdashuj ...

  6. python java混合编程_详解java调用python的几种用法(看这篇就够了)

    java调用python的几种用法如下: 在java类中直接执行python语句 在java类中直接调用本地python脚本 使用Runtime.getRuntime()执行python脚本文件(推荐 ...

  7. 面试率 90% 的JS事件循环Event Loop,看这篇就够了!! !

    面试率 90% 的JS事件循环Event Loop,看这篇就够了!! ! 事件循环(Event Loop)大家应该并不陌生,它是前端极其重要的基础知识.在平时的讨论或者面试中也是一个非常高频的话题. ...

  8. NDK撩妹三部曲(四)—NDK 开发如何优雅的定位 Native 异常,看这篇就够了

    NDK 开发如何优雅的定位 Native 异常,看这篇就够了 从何说起? 摘要 案例实操 aaddr2line objdump ndk-stack 1.假设我们已经通过 adb logcat 拿到了程 ...

  9. Java String,看这篇就够了

    String,是Java中最重要的类.这句肯定的推断不是Java之父詹姆斯·高斯林说的,而是沉默王二说的,因此你不必怀疑它的准确性. 关于字符串,有很多的面试题,但我总觉得理论知识绕来绕去没多大意思. ...

最新文章

  1. MySQL批量检查表的脚本
  2. 【 ML 】Steepest Descent Iteration Procedure of TOA - Based Positioning Simulation
  3. 编译-C语言库FFTW支持iOS平台的静态库
  4. 中的实践 中兴_中兴通讯5G智慧治水业务在千岛湖畔下姜村成功实践
  5. php 伪静态 获取当前页面路径_织梦移动适配PHP获取当前页面URL地址方法
  6. java 抽象类_java中的抽象类
  7. 价值80元的emlog博客用户注册插件
  8. CF1109F Sasha and Algorithm of Silence's Sounds LCT、线段树
  9. java保存视频到本地
  10. 【染上你的颜色】MMD动作+镜头下载
  11. ARM PWN基础教程
  12. 拨号不能建立远程计算机的连接,彻底解决Win8、Win10系统宽带拨号出现“错误720:不能建立到远程计算机的连接”的问题...
  13. Springboot配置suffix指定mvc视图的后缀
  14. [转]开源软件名的读音
  15. Android仿淘宝头条垂直滚动,垂直走马灯,公告
  16. 人工智能与智能的异同
  17. 子类重写方法不能抛出新的异常
  18. 过敏性鼻炎、感冒、哮喘
  19. 记录一次Oracle自动化测试工具 - OATS实战分享
  20. SSM研究生推免网站

热门文章

  1. 音频格式转换的软件有哪些?这些软件值得收藏
  2. Mysql创建一张表并且添加一万条数据
  3. mysql自带的邮件发送功能_Python实现的查询mysql数据库并通过邮件发送信息功能...
  4. 25个基于浏览器的HTML在线编辑器集合
  5. MacBook Big Sur 完美解决外接显示器 字体模糊、边缘不清 HIDPI 解决办法
  6. android 和风天气 调用示例,Android中 GsonFormat插件解析Jason 数据+和风天气接口解析案例(示例代码)...
  7. CVPR 2021 论文大盘点-图像修复篇
  8. Detour安装及简单使用实例
  9. flask中redirect用法
  10. vue+element实现图片上传及裁剪功能(vue-cropper)