Gson&FastJson解析异常Json的处理

您所在的位置:网站首页 黄疸肝炎的饮食 Gson&FastJson解析异常Json的处理

Gson&FastJson解析异常Json的处理

2023-11-23 09:57| 来源: 网络整理| 查看: 265

这几天因为开发需求对项目中Json的解析做了一下整理。在整理的过程中遇到比较大的问题,就是后端没按约定返回字段值,以及空字符串(”“、“null”)等情况。某度和某哥了一下,发现遇到这个问题的朋友还是挺多的。于是趁热打铁总结了一下解决方案奉献给大家。

Gson和FastJson的恩怨情仇

FastJson是阿里开源的一个Json解析项目,其内部使用了各种方案使得Json序列化和反序列化的速度提升到了极致。而Gson则是Google开源的,据说可以解析一些FastJson解析不了的超复杂json结构(这个本人也没实际验证过,欢迎大家亲自去实践检验),解析速度相对要慢些。 如果不是十分地追求解析的效率,或者遇到一些无法解析的json结构,我觉得选择FastJson或者Gson都是可以的。 不过相信很多人的项目都集成了不止一种的Json解析库,FastJson、Gson、Jackson之类都可能混搭着使用,我们的项目也不例外,同时使用了FastJson和Gson。我在整理Json解析的过程中,考虑到很多开源项目和Google官方的支持,想将Json解析写到一个工具类中,统一换成用Gson解析。但实践后发现了个比较严重的问题。 FastJson在反序列化的时候,是对大小写不敏感的。也就是如下面这样的json串,“DaTa”字段的大小写不一,也可以解析到“data”字段。

{ "DaTa": "android" } private String data;

而在序列化的时候,则默认又是会将首字母置为小写。如下

private String Data;

会序列化成

{“data”: "android" }

当然,这个问题可以用@JSONField注解来解决

@JSONField(name = "Data") private String data; \\注意这里要小写开头

则会序列化成

{“Data”: "android" }

而相对于Gson,则完全是对字段名大小写敏感的,无论是序列化还是反序列化。也就是说,如果我们之前的模型没注意大小写的规范,用FastJson将后台json解析成前台对象时,是完全没问题的;而如果换成Gson则有可能解析失败。 这个坑埋得还是比较深,毕竟谁也没办法保证经过那么多手的代码,在属性大小写上是完全正确的。鉴于这个问题,目测还是得Gson和FastJson两者并行使用了。所以如果打算从FastJson转到Gson的朋友们,要切记注意这个细节!

异常情况

假设我们和后端约定Json数据格式如下:

{ "code":1 , "msg":"成功" , "Data":{"id":1,"name":"王小二" } } { "code":1 , "msg":"成功" , "Data":[{"id":1,"name":"王小二" },{"id":2,"name":"马大三" }] }

于是数据模型就可以这样定义:

/** * HttpResult.java */ public class HttpResult { private int code; private String msg; private T Data; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return Data; } public void setData(T data) { Data = data; } } /** * UserInfo.java */ public class UserInfo { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

解析过程就像下面这么写。其中,JsonParseUtil是封装的Json解析工具类,文章最后会有全部源码;GenericType则是为了统一FastJson和Gson两个库对泛型解析的通用类,和FastJson的TypeReference、Gson的TypeToken类似,都是通过ParameterizedType来获取泛型类型指定的实际类型。

HttpResult httpResult = JsonParseUtil.parseToGenericObject(jsonStr, new GenericType(){}); /** * JsonParseUtil.java */ public static T parseToGenericObject(String dataStr, GenericType genericType) { if (TextUtils.isEmpty(dataStr)) { return null; } //Gson解析 /*T t = getSingleton().fromJson(dataStr, genericType.getType());*/ //FastJson解析 T t = JSON.parseObject(dataStr, genericType.getType()); return t; }

一切似乎都那么顺其自然、一切似乎都那么的简单……噢耶!提交代码,准备下班了! 啪~正准备关机的时候,程序突然崩掉了,无论用FastJson还是Gson都一个样,仔细看了下后端返回的Json串,发现了问题所在,坑终究还是出现了。

情景1-定义整型字段,返回字符串“”

后台返回如下:

{ "code":1 , "msg":"成功" , "Data":{"id":"","name":"" } }

属性id是定义了int类型的,却返回了空字符串“”. 对于这种情况FastJson是做了容错处理的,底层直接会将字符串转成整型,当然如果非法字符转Integer失败也会报错。 相对来说Gson则没那么智能,不过我们可以通过实现JsonDeserializer接口,自定义序列化来解决。

/** * IntegerGsonDeserializer.java */ public class IntegerGsonDeserializer implements JsonDeserializer { @Override public Integer deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { try { //默认后台返回"" 或者 "null",则设置默认值为 0 if (jsonElement.getAsString().equals("") || jsonElement.getAsString().equals("null")) { return 0; } } catch (Exception e) { } try { return jsonElement.getAsInt(); } catch (NumberFormatException e) { throw new JsonSyntaxException(e); } } }

并且我们在程序最开始注册使用以上自定义反序列化的类型

/** * Application.java */ JsonParseUtil.setSingletonInstance( new GsonBuilder() .registerTypeAdapter(Integer.class, new IntegerGsonDeserializer()) .registerTypeAdapter(int.class, new IntegerGsonDeserializer()) .create()); 情景2-泛型Data无数据时,返回空字符串”“

后台返回如下:

{ "code":1 , "msg":"成功" , "Data":"" }

这是由于泛型Data实际上是一个Json对象或者数组,而在Json里面空字符串不属于Json对象导致的解析出错,所以返回的Data必须是{}或者[]。 这个问题,在Gson中,我们同样通过实现JsonDeserializer接口,自定义反序列化操作来解决。

/** * HttpResultGsonDeserializer.java */ public class HttpResultGsonDeserializer implements JsonDeserializer


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3