您的位置:首页 > 移动开发 > Android开发

Android Study 之 彻底解决 Gson解析 异常 :com.google.gson.JsonSyntaxException

2017-10-28 11:22 567 查看
LZ-Say:大风呼呼的刮,就好像妖精要来的前奏一样~



前言

开发过程中,App常用的接收参数的时候,几乎大部分都是以json格式为主,那么有关解析json的方式有很多,Android端相对来说使用Gson比较多,而在解析过程中,如果你遇到规范的后台,那你大可放心随便浪,But,如果遇到神后台,那么,呵呵了你就。真的想不到还会出现什么问题。。。



描述问题

实现某个功能,调用某个接口,返回如下参数:

{
"areaName": null,
"accountId": 138,
"accountName": null,
"accountNumber": null,
"msgCode": "",
"msg": "",
"pname": "赵九胜",
"nation": "19701010",
"imgUri": null,
"phone": "15831345807",
"areaCode": "230303",
"usedTime": null,
"collectionWay": 1,
"registTime": null,
"createTime": "2017-10-26 06:46:23",
"amount": 580,
"price": 0,
"certificates": null,
"certificatesPhotos": null
}


大家仔细观察下,咋眼一看,也没啥问题是不?

可在解析的过程中,GG了。。。

趟坑路,超神路

满怀信心的撸码,运行,app却提示了如下类型错误:

com.google.gson.JsonSyntaxException

上来一看,Json格式错误?回头再仔细看下返回的Json。

有的值为null,有的值为“”

重点结合度娘的意见以及重新回顾Json串时,确定了是由于后台接口参数返回不规范(也就是设计不合理)导致解析失败。



那么怎么解决呢?

其实说白了,就是在转化解析的过程中对后台返回Json中不合法的属性字段进行有效处理即可。具体直接看下面工具类即可。

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class GsonUtil {

/**
* 实现格式化的时间字符串转时间对象
*/
private static final String DATEFORMAT_default = "yyyy-MM-dd HH:mm:ss";

/**
* 使用默认的gson对象进行反序列化
*
* @param json
* @param typeToken
* @return
*/
public static <T> T fromJsonDefault(String json, TypeToken<T> typeToken) {
Gson gson = new Gson();
return gson.fromJson(json, typeToken.getType());
}

/**
* json字符串转list或者map
*
* @param json
* @param typeToken
* @return
*/
public static <T> T fromJson(String json, TypeToken<T> typeToken) {
Gson gson = new GsonBuilder()
// 重写map的反序列化
.registerTypeAdapter(new TypeToken<Map<String, Object>>() {
}.getType(), new MapTypeAdapter()).create();
return gson.fromJson(json, typeToken.getType());
}

/**
* json字符串转bean对象
*
* @param json
* @param cls
* @return
*/
public static <T> T fromJson(String json, Class<T> cls) {
Gson gson = new GsonBuilder().setDateFormat(DATEFORMAT_default)
.create();
return gson.fromJson(json, cls);
}

/**
* 对象转json
*
* @param obj
* @param format
* @return
*/
public static String toJson(Object obj, boolean format) {
GsonBuilder gsonBuilder = new GsonBuilder();
//  设置默认时间格式
gsonBuilder.setDateFormat(DATEFORMAT_default);
// 添加格式化设置
if (format) {
gsonBuilder.setPrettyPrinting();
}
Gson gson = gsonBuilder.create();
return gson.toJson(obj);
}

public static class MapTypeAdapter extends TypeAdapter<Object> {

@Override
public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
switch (token) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList<Object>();
in.beginArray();
while (in.hasNext()) {
list.add(read(in));
}
in.endArray();
return list;
case BEGIN_OBJECT:
Map<String, Object> map = new LinkedTreeMap<String, Object>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER:
// 改写数字的处理逻辑,将数字值分为整型与浮点型。
double dbNum = in.nextDouble();
// 数字超过long的最大值,返回浮点类型
if (dbNum > Long.MAX_VALUE) {
return dbNum;
}
// 判断数字是否为整数值
long lngNum = (long) dbNum;
if (dbNum == lngNum) {
return lngNum;
} else {
return dbNum;
}
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}

@Override
public void write(JsonWriter out, Object value) throws IOException {
// 序列化无需实现
}

}

}


调用方式如下:

List<SearchResultBean> resultBean = GsonUtil.fromJson(
GsonUtil.toJson(result.getData(), true),  // 这里需要将获取到的json再次进行格式化
new TypeToken<List<SearchResultBean>>() {
});


结束

其实 度娘有度娘的好处

开发者 好多包括LZ 都是属于“百度开发者”但是这点并没有什么可傲娇的

能做的 就是在前行的路上 不断充实自己 加油 各位伙计们
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐