Gson解析空字符串異常的處理

面對一些不規范的json,我們的gson解析經常會拋出各種異常導致app崩潰,這里可以采取一些措施來避免


11月9日更新:
關于數組類型的字段解析異常,我嘗試了一些方案,但最后都存在問題,如果大家有好的解決方案,希望能貼在下面.不甚感激.
異常示例=>正常json:

{
    "code":0,
    "msg":"ok",
    "data":[    //約定為數組
      {
        "id":5638,
        "newsId":5638
      }
      ]
}

異常json:

{
    "code":0,
    "msg":"ok",
    "data":{}    //返回為對象或者空字符串
}

Json異常情況

先來看一個后臺返回的json
正常情況下json:

{
    "code":0,
    "msg":"ok",
    "data":{
        "id":5638,
        "newsId":5638
    }
}

data部分對應的實體類:

public class JsonBean {
    private int id;
    private int newsId;

    public int getId() {
        return id;
    }

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

    public int getNewsId() {
        return newsId;
    }

    public void setNewsId(int newsId) {
        this.newsId = newsId;
    }
}

異常情況json(后臺數據庫newsId字段未查詢到對應數據):

{
    "code":0,
    "msg":"ok",
    "data":{
        "id":5638,
        "newsId":""
    }
}

這樣Gson在解析時就會拋出解析錯誤的異常,app崩潰,原因是無法將""轉化為int

json異常的處理

我們期望在后臺返回的json異常時,也能解析成功,空值對應的轉換為默認值,如:newsId=0;
這里排除掉后臺開發人員輸出時給你做矯正,還是得靠自己啊---

我們寫一個針對int值的類型轉換器,需要實現Gson的JsonSerializer<T>接口和JsonDeserializer<T>,即序列化和反序列化接口

public class IntegerDefault0Adapter implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
    @Override
    public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        try {
            if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定義為int類型,如果后臺返回""或者null,則返回0
                return 0;
            }
        } catch (Exception ignore) {
        }
        try {
            return json.getAsInt();
        } catch (NumberFormatException e) {
            throw new JsonSyntaxException(e);
        }
    }

    @Override
    public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(src);
    }
}

同理Long及Double類型

double=>

public class DoubleDefault0Adapter implements JsonSerializer<Double>, JsonDeserializer<Double> {
    @Override
    public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        try {
            if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定義為double類型,如果后臺返回""或者null,則返回0.00
                return 0.00;
        }
            } catch (Exception ignore) {
        }
        try {
            return json.getAsDouble();
        } catch (NumberFormatException e) {
            throw new JsonSyntaxException(e);
        }
    }

    @Override
    public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(src);
    }
}

long=>

public class LongDefault0Adapter implements JsonSerializer<Long>, JsonDeserializer<Long> {
    @Override
    public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {
        try {
            if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定義為long類型,如果后臺返回""或者null,則返回0
                    return 0l;
                }
            } catch (Exception ignore) {
        }
        try {
            return json.getAsLong();
        } catch (NumberFormatException e) {
            throw new JsonSyntaxException(e);
        }
    }

    @Override
    public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(src);
    }
}

所以使用是這樣的:

return new Retrofit.Builder()
       .client(okHttpClient)//設置網絡訪問框架
       .addConverterFactory(GsonConverterFactory.create(buildGson()))//添加json轉換框架
       .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//讓Retrofit支持RxJava
       .baseUrl(baseUrl)
       .build();

/**
 * 增加后臺返回""和"null"的處理
 * 1.int=>0
 * 2.double=>0.00
 * 3.long=>0L
 *
 * @return
 */
public static Gson buildGson() {
    if (gson == null) {
        gson = new GsonBuilder()
                .registerTypeAdapter(Integer.class, new IntegerDefault0Adapter())
                .registerTypeAdapter(int.class, new IntegerDefault0Adapter())
                .registerTypeAdapter(Double.class, new DoubleDefault0Adapter())
                .registerTypeAdapter(double.class, new DoubleDefault0Adapter())
                .registerTypeAdapter(Long.class, new LongDefault0Adapter())
                .registerTypeAdapter(long.class, new LongDefault0Adapter())
                .create();
    }
    return gson;
}

再也不會因為后臺json字段為空的情況崩潰了

關于作者

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.概述2.Gson的目標3.Gson的性能和擴展性4.Gson的使用者5.如何使用Gson 通過Maven來使用...
    人失格閱讀 14,344評論 2 18
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • 點擊查看原文 Web SDK 開發手冊 SDK 概述 網易云信 SDK 為 Web 應用提供一個完善的 IM 系統...
    layjoy閱讀 13,934評論 0 15
  • 這個文章比較“膚淺”,但是其實網上對于Fragment切換這么膚淺的事情也甚少有文章說的清楚,所以稍微介紹下。 B...
    聰蔥忙忘閱讀 9,037評論 13 8
  • 徐云霞說道 :“既然胡大哥有祖訓在身小弟也不便勉強,只是小弟仍有一事相求,還望胡大哥應允。” 胡斐說道 :“雖然胡...
    長白居士閱讀 274評論 0 0