Gson 解析服务端返回的多种类型的 JSON

Posted code小生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gson 解析服务端返回的多种类型的 JSON相关的知识,希望对你有一定的参考价值。

 关注 code小生 ,每日一篇技术推送!

遇到几种Json类型,使用Gson通过自定义解析器解析一下几种类型的返回数据。

JSON示例

返回Json中data为空

{
   "data": "",
   "code": 1,
   "message": "请求失败"
}

返回Json中data值为null

{
   "data": null,
   "code": 1,
   "message": "请求失败"
}

返回Json中data为对象类型

{
   "data": {
       "name": "秦川小将",
       "phone": "182******08"
   },
   "code": 0,
   "message": "请求成功"
}

返回Json中的data为集合类型

{
   "data": [{
       "name": "张三",
       "phone": "182******08"
   }, {
       "name": "李四",
       "phone": "182******08"
   }],
   "code": 0,
   "message": "请求成功"
}

返回Json中的data的值为字符串,解析时需要去除转义字符拿到具体的对象

{
 "data": "{\"id\":2981,\"title\":\"除夕活动启动页\",\"content\":\"\",\"url\":\"http://np.test.com/Activity/MonsterNian20180215\"}",
 "code": 0,
 "message": "请求成功"
}

返回Json中的data的值为字符串,解析时需要去除转义字符拿到具体的集合对象

{
 "data": "[{\"id\":2981,\"title\":\"除夕活动启动页\",\"content\":\"\",\"url\":\"http://np.test.com/Activity/MonsterNian20180215\"},{\"id\":2849,\"title\":\"默认启动页\",\"content\":\"\",\"url\":\"\"}]",
 "code": 0,
 "message": "请求成功"
}

定义基础类

为了防止重复写除data值以外的属性,这里定义一个基础类。

public class ResultData<T> {

   public T data;
   public int code;
   public String message;
   /**
    * 扩展字段
    * 0:data为对象
    * 1:data为集合
    * 2:date为空或者null字段
    */

   public int dataType;  

   public T getData() {
       return data;
   }

   public void setData(T data) {
       this.data = data;
   }

   public int getCode() {
       return code;
   }

   public void setCode(int code) {
       this.code = code;
   }

   public String getMessage() {
       return message;
   }

   public void setMessage(String message) {
       this.message = message;
   }

   public int getDataType() {
       return dataType;
   }

   public void setDataType(int dataType) {
       this.dataType = dataType;
   }

   @Override
   public String toString() {
       return "{" +
               "data=" + data +
               ", code=" + code +
               ", message='" + message + '\'' +
               ", dataType=" + dataType +
               '}';
   }
}

自定义解析器

实现 JsonDeserializer 接口重写 deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 方法,这里进行解析处理,针对特殊字段特殊处理。

public class JsonFormatParser implements JsonDeserializer<ResultData> {

   private Class mClass;

   public JsonFormatParser(Class tClass) {
       this.mClass = tClass;
   }

   @Override
   public ResultData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
       // 根据Json元素获取Json对象。
       JsonObject mJsonObject = json.getAsJsonObject();
       ResultData mResult = new ResultData();
       // 由于Json是以键值对的形式存在的,此处根据键(data)获取对应的Json字符串。
       String mJson = mJsonObject.get("data").toString();
       // 判断是Array还是Object类型。
       if (mJsonObject.get("data").isJsonArray() && !mJsonObject.get("data").isJsonNull()) {
           mResult.setData(fromJsonArray(mJson, mClass));
           mResult.setDataType(1);
       } else if (mJsonObject.get("data").isJsonObject() && !mJsonObject.get("data").isJsonNull()) {
           mResult.setData(fromJsonObject(mJson, mClass));
           mResult.setDataType(0);
       } else if (mJsonObject.get("data").isJsonPrimitive() && !mJsonObject.get("data").isJsonNull()) {
           // 服务端返回data的值为"{}","[]",将对象或者集合以字符串的形式返回回来,先去除两边的双引号,再去掉转义字符。
           String mNewJson = mJson.substring(1, mJson.length() - 1).replaceAll("\\\\", "");
           // 根据处理好的Json字符串判断是集合还是对象,再进行解析。
           if (mNewJson.startsWith("[") || mNewJson.endsWith("]")) {
               mResult.setData(fromJsonArray(mNewJson, mClass));
               mResult.setDataType(1);
           } else if (mNewJson.startsWith("{") || mNewJson.endsWith("}")) {
               mResult.setData(fromJsonObject(mNewJson, mClass));
               mResult.setDataType(0);
           } else {
               mResult.setData(fromJsonObject(mResult.toString(), mClass));
               mResult.setDataType(2);
           }
       } else if (mJsonObject.get("data").isJsonNull() || mJsonObject.get("data").getAsString().isEmpty()) {
           mResult.setData(fromJsonObject(mResult.toString(), mClass));
           mResult.setDataType(2);
       }
       // 根据键获取返回的状态码。
       mResult.setCode(mJsonObject.get("code").getAsInt());
       // 根据键获取返回的状态信息。
       mResult.setMessage(mJsonObject.get("message").getAsString());
       return mResult;
   }

   /**
    * 用来解析对象
    */

   private <T> T fromJsonObject(String json, Class<T> type) {
       return new Gson().fromJson(json, type);
   }

   /**
    * 用来解析集合
    */

   private <T> ArrayList<T> fromJsonArray(String json, Class<T> clazz) {
       Type type = new TypeToken<ArrayList<JsonObject>>() {
       }.getType();
       ArrayList<JsonObject> jsonObjects = new Gson().fromJson(json, type);
       ArrayList<T> arrayList = new ArrayList<>();
       for (JsonObject jsonObject : jsonObjects) {
           arrayList.add(new Gson().fromJson(jsonObject, clazz));
       }
       return arrayList;
   }
}

Gson配置

public class FromJsonUtils {

   public static ResultData fromJson(String json, Class clazz) {
       return new GsonBuilder()
               .registerTypeAdapter(ResultData.class, new JsonFormatParser(clazz))
               .enableComplexMapKeySerialization()
               .serializeNulls()
               .create()
               .fromJson(json, ResultData.class);
   }
}

具体调用

public class JsonTest {

   private static final String mJson1 = "{\"data\": \"\", \"code\": 1, \"message\": \"请求失败\"}";
   private static final String mJson2 = "{\"data\": null, \"code\": 1, \"message\": \"请求失败\"}";
   private static final String mJson3 = "{\"data\": {\"name\": \"秦川小将\", \"phone\": \"182******08\"}, \"code\": 0, \"message\": \"请求成功\"}";
   private static final String mJson4 = "{\"data\": [{\"name\": \"张三\", \"phone\": \"182******08\"},{\"name\": \"李四\", \"phone\": \"182******08\"}],\"code\": 0, \"message\": \"请求成功\"}";
   private static final String mJson5 = "{\"data\":\"{\\\"id\\\":2981,\\\"title\\\":\\\"除夕活动启动页\\\",\\\"content\\\":\\\"\\\",\\\"url\\\":\\\"http://np.test.com/Activity/MonsterNian20180215\\\"}\",\"code\":0,\"message\":\"请求成功\"}";
   private static final String mJson6 = "{\"data\":\"[{\\\"id\\\":2981,\\\"title\\\":\\\"除夕活动启动页\\\",\\\"content\\\":\\\"\\\",\\\"url\\\":\\\"http://np.test.com/Activity/MonsterNian20180215\\\"},{\\\"id\\\":2849,\\\"title\\\":\\\"默认启动页\\\",\\\"content\\\":\\\"\\\",\\\"url\\\":\\\"\\\"}]\",\"code\":0,\"message\":\"请求成功\"}";

   public static void main(String[] args) {
       ResultData<DataBean> mData1 = FromJsonUtils.fromJson(mJson1, DataBean.class);
       System.out.print("数据类型:" + mData1.getDataType() + "\t解析后取值:" + mData1.getData().getName() + "\n");
       System.out.print("====================================" + "\n");

       ResultData<DataBean> mData2 = FromJsonUtils.fromJson(mJson2, DataBean.class);
       System.out.print("数据类型:" + mData2.getDataType() + "\t解析后取值:" + mData2.getData().getName() + "\n");
       System.out.print("====================================" + "\n");

       ResultData<DataBean> mData3 = FromJsonUtils.fromJson(mJson3, DataBean.class);
       System.out.print("数据类型:" + mData3.getDataType() + "\t解析后取值:" + mData3.getData().getName() + "\n");
       System.out.print("====================================" + "\n");

       ResultData<List<DataBean>> mData4 = FromJsonUtils.fromJson(mJson4, DataBean.class);
       for (DataBean mData : mData4.getData()) {
           System.out.print("数据类型:" + mData4.getDataType() + "\t解析后取值:" + mData.getName() + "\n");
       }
       System.out.print("====================================" + "\n");

       ResultData<ActivityBean> mData5 = FromJsonUtils.fromJson(mJson5, ActivityBean.class);
       System.out.print("数据类型:" + mData5.getDataType() + "\t解析后取值:" + mData5.getData().getTitle() + "\n");
       System.out.print("====================================" + "\n");

       ResultData<List<ActivityBean>> mData6 = FromJsonUtils.fromJson(mJson6, ActivityBean.class);
       for (ActivityBean mActivity : mData6.getData()) {
           System.out.print("数据类型:" + mData6.getDataType() + "\t解析后取值:" + mActivity.getTitle() + "\n");
       }
   }
}

打印输出:

数据类型:2    解析后取值:null
====================================
数据类型:2    解析后取值:null
====================================
数据类型:0    解析后取值:秦川小将
====================================
数据类型:1    解析后取值:张三
数据类型:1    解析后取值:李四
====================================
数据类型:0    解析后取值:除夕活动启动页
====================================
数据类型:1    解析后取值:除夕活动启动页
数据类型:1    解析后取值:默认启动页

示例数据实体类

public class DataBean {

   public String name;

   public String phone;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String getPhone() {
       return phone;
   }

   public void setPhone(String phone) {
       this.phone = phone;
   }

}
public class ActivityBean {

   private int id;
   private String title;
   private String content;
   private String url;

   public int getId() {
       return id;
   }

   public void setId(int id) {
       this.id = id;
   }

   public String getTitle() {
       return title;
   }

   public void setTitle(String title) {
       this.title = title;
   }

   public String getContent() {
       return content;
   }

   public void setContent(String content) {
       this.content = content;
   }

   public String getUrl() {
       return url;
   }

   public void setUrl(String url) {
       this.url = url;
   }
}



以上是关于Gson 解析服务端返回的多种类型的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

JSON 之GSON 解析

GSON JSON解析返回null

解决PHP服务端返回json字符串有特殊字符的问题

采用Gson解析含有多种JsonObject的复杂json

Json介绍

使用 gson 解析成 POJO 时,Json 总是返回 null