android gson的使用

項(xiàng)目中一直使用的原生解析JSONObject.
參考鏈接http://www.itdecent.cn/p/e740196225a4#
基于Gson V2.8.5

序列化: 把Java對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程。 eg:toJson(對(duì)象)
反序列化:把字節(jié)序列恢復(fù)為Java對(duì)象的過(guò)程。eg:fromJson("字節(jié)序列",對(duì)象)

Gson基本用法

  • toJson序列化.
public String toJson(Object src) {
public String toJson(Object src, Type typeOfSrc) {}
public void toJson(Object src, Appendable writer) throws JsonIOException {}
public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {}
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {}
public String toJson(JsonElement jsonElement) {}
public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {}
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {}
  • fromJson反序列化.
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {}
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {}
public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {}
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {}
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {}
public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {}
public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {}

基本數(shù)據(jù)類型的生成、

        Gson gson=new Gson();
        String jsonString=gson.toJson("java");//java
        String jsonNumber=gson.toJson(2018);//2018
        String jsonBoolean=gson.toJson(true);//true

POJO類的生成與解析普通java類

String jsonResponse="{
    "code": 200,
    "msg": "OK",
    "user": [
        {
            "name": "cqx1",
            "age": "2018",
            "phone": "166...111",
            "email": "183xxxx111@qq.com"
        },
        {
            "name": "cqx2",
            "age": "2018",
            "phone": "166...222",
            "email": "183xxxx222@qq.com"
        }
    ]
}";

  private class StudentEntity {
        private String code;
        @Expose
        private String msg;
        /**
         * 此處user為json串的key,下面的userList為自己定義的別名
         */
        @SerializedName("user")
        private List<UserEntity> userList;

  private class UserEntity {
        private String name;
        private String age;
        private String phone;
        private String emails;
        ...

如果此時(shí)按照以下解析,哪怕try catch也攔截不到。

 /**
     * 從raw包下讀取數(shù)據(jù)
     * @param context
     * @param rawName   R.raw.cqx
     * @return
     */
    public static String getFileStremFromRaw(Activity context, int rawName) {
        try {
            InputStreamReader inputReader = new InputStreamReader(context.getResources().openRawResource(rawName));
            BufferedReader bufReader = new BufferedReader(inputReader);
            String line = "";
            String Result = "";
            while ((line = bufReader.readLine()) != null)
                Result += line;
            return Result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
    

解析上面的報(bào)文。

 private void parseJsonReponse() {
        String response = FileTools.getFileStremFromRaw(this, R.raw.test);
        JsonParser jsonParser = new JsonParser();
        JsonObject jsonObject = jsonParser.parse(response).getAsJsonObject();
        try {

//因?yàn)閷?duì)應(yīng)的為Object,所以這樣的解析就會(huì)異常崩潰,并且攔截?zé)o用。
            JsonArray jsonArray = jsonParser.parse(response).getAsJsonArray();
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
        }
        String msg=jsonObject.get("msg").getAsString();
    }

錯(cuò)誤日志如下:

     Caused by: java.lang.IllegalStateException: Not a JSON Array: {"code":200,"msg":"OK","user":[{"name":"cqx1","age":"2018","phone":"166...111","email":"183xxxx111@qq.com"},{"name":"cqx2","age":"2018","phone":"166...222","email":"183xxxx222@qq.com"}]}
        at com.google.gson.JsonElement.getAsJsonArray(JsonElement.java:107)
        at com.cc.rxjava.gson.GsonActivity.parseJsonReponse(GsonActivity.java:76)
        at com.cc.rxjava.gson.GsonActivity.onCreate(GsonActivity.java:68)
        at android.app.Activity.performCreate(Activity.java:6715)

然后實(shí)際開(kāi)發(fā)中,后臺(tái)返回的json格式可能跟我們要的不一致,如果線上的因?yàn)楹笈_(tái)返回的數(shù)據(jù)格式而崩潰,哪怕最終查出原因是后臺(tái)的問(wèn)題,最終客戶端還是得背鍋,誰(shuí)叫沒(méi)有做容錯(cuò)處理呢。
如果服務(wù)端返回的為正確的數(shù)據(jù)解析方式:

    private void parseJsonReponse() {
        String response = FileTools.getFileStremFromRaw(this, R.raw.test);
        StudentEntity studentEntity = new Gson().fromJson(response, StudentEntity.class);
        Type type =new TypeToken<StudentEntity>(){}.getType();
        StudentEntity studentEntity2 = new Gson().fromJson(response, type);
//        userList = studentEntity.userList;
    }

json的生成

將對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程。toJson

  Gson gson = new Gson();
  UserEntity user = new UserEntity("cc","2018","1660....","183...@qq.com");
  String jsonObject = gson.toJson(user);//{"age":"2018","emails":"183...@qq.com","name":"cc","phone":"1660...."}

解析Json

將字節(jié)系列轉(zhuǎn)為為對(duì)象的過(guò)程。fromJson

UserEntity userEntity = gson.fromJson(jsonObject, UserEntity.class);

List<UserEntity> list = gson.fromJson(jsonArray, new TypeToken<List<UserEntity>>() {
        }.getType());

數(shù)組

String[] strings = gson.fromJson(jsonArray, String[].class);

List

 List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());

@Expose、@SerializeName注解

json解析的字段(key)的名稱和類型是一一對(duì)應(yīng)的,當(dāng)客戶端和后臺(tái)使用的語(yǔ)言不同,二者語(yǔ)言命名規(guī)范不同,命名規(guī)則常常不統(tǒng)一的情況下,使用@Expose和@SerializeName注解。
@Expose注解:區(qū)分實(shí)體中序列號(hào)的屬性,包含兩個(gè)屬性,deserialize(反序列化)和serialize(序列化),默認(rèn)為true。使用@Expose進(jìn)行序列化,如果不想被序列化也可以使用transient。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Expose {
  
  /**
   * If {@code true}, the field marked with this annotation is written out in the JSON while
   * serializing. If {@code false}, the field marked with this annotation is skipped from the
   * serialized output. Defaults to {@code true}.
   * @since 1.4
   */
  public boolean serialize() default true;

  /**
   * If {@code true}, the field marked with this annotation is deserialized from the JSON.
   * If {@code false}, the field marked with this annotation is skipped during deserialization. 
   * Defaults to {@code true}.
   * @since 1.4
   */
  public boolean deserialize() default true;
}

@SerializeName注解:屬性重命名

//使用這樣的方式創(chuàng)建gson對(duì)象。
Gson gson=new Gson().newBuilder().excludeFieldsWithoutExposeAnnotation().create();
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface SerializedName {

  /**
   * @return the desired name of the field when it is serialized or deserialized
   */
  String value();
  /**
   * @return the alternative names of the field when it is deserialized
   */
  String[] alternate() default {};
}

用例

@SerializedName("email_address")
public String emailAddress;

如果存在一個(gè)key多個(gè)寫(xiě)法,則可以選擇@SerializeName的alternate別名的選擇,根據(jù)以上代碼可知為一個(gè)字符串?dāng)?shù)組。

借用例子
{"name":"怪盜kidou","age":24,"emailAddress":"ikidou@example.com"}
{"name":"怪盜kidou","age":24,"email_address":"ikidou@example.com"}
{"name":"怪盜kidou","age":24,"email":"ikidou@example.com"}
作者:怪盜kidou
鏈接:http://www.itdecent.cn/p/e740196225a4#

所以處理辦法是:

@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;

多個(gè)情況同時(shí)存在時(shí):
Gson gson = new Gson();
String json = "{\"name\":\"怪盜kidou\",\"age\":24,\"emailAddress\":\"ikidou_1@example.com\",\"email\":\"ikidou_2@example.com\",\"email_address\":\"ikidou_3@example.com\"}";
User user = gson.fromJson(json, User.class);
System.out.println(user.emailAddress); // ikidou_3@example.com

作者:怪盜kidou
鏈接:http://www.itdecent.cn/p/e740196225a4#

補(bǔ)充demo

image.png


如上圖可以看到該json格式為外層JsonObject,里面有個(gè)key為rltInfo的JsonObject,rltInfo里面存在兩個(gè)JsonArray的數(shù)組list.可以簡(jiǎn)易封裝一下解析:

//基類
public class BaseResult<T> {
    public boolean rltFlag;
    public RltInfoEntity<T> rltInfo;

}

public class RltInfoEntity<T> {
    public String status;
    public String statusDesc;
    @SerializedName("taskList")
    public List<T> mGcTaskList;
//mShTaskList客戶端命名規(guī)則,shTaskList為服務(wù)端返回來(lái)的json的key
    @SerializedName("shTaskList")
    public List<T> mShTaskList;
}

/**
 * created by cheng.qx on 2018/8/20 17:10
 */
public class XJTaskEntity {
    /**
     * 任務(wù)ID
     */
    private String taskId;

    /**
     * 任務(wù)名稱
     */
    private String taskName;

    /**
     * 所屬用戶ID
     */
    private String personId;

    /**
     * 所屬用戶名稱
     */
    private String personName;

    /**
     * 門店ID
     */
    private String storeId;

    /**
     * 門店名稱
     */
    @SerializedName("orgName")
    private String storeName;

    /**
     * 區(qū)域ID
     */
    private String areaId;

    /**
     * 區(qū)域名稱
     */
    private String areaName;

    /**
     * 任務(wù)開(kāi)始時(shí)間-天
     */
    @SerializedName(value ="beginTimeStr",alternate={"submitTimeStr"})
    private String taskBeginDay;

    /**
     * 任務(wù)開(kāi)始時(shí)間-時(shí)分秒
     */
    private String taskBeginHour;

    /**
     * 任務(wù)結(jié)束時(shí)間-天
     */
    @SerializedName("endTimeStr")
    private String taskEndDay;

    /**
     * 任務(wù)結(jié)束時(shí)間-時(shí)分秒
     */
    private String taskEndHour;

在Activity中解析數(shù)據(jù):

   private void initParseToDoList() {
        try {
            String response = FileTools.getFileStremFromRaw(activityContext, R.raw.done_gson);
            Gson gson = new Gson();
            Type type = new TypeToken<BaseResult<XJTaskEntity>>() {
            }.getType();
            BaseResult<XJTaskEntity> baseResult = gson.fromJson(response, type);
            if (baseResult.rltInfo.mGcTaskList != null) {
                taskList.addAll(baseResult.rltInfo.mGcTaskList);
            }
            if (baseResult.rltInfo.mShTaskList != null) {
                taskList.addAll(baseResult.rltInfo.mShTaskList);
            }
            mGsonAdapter.notifyDataSetChanged();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 從raw包下讀取數(shù)據(jù)
     *
     * @param context
     * @param rawName R.raw.cqx
     * @return
     */
    public static String getFileStremFromRaw(Activity context, int rawName) {
        try {
            InputStreamReader inputReader = new InputStreamReader(context.getResources().openRawResource(rawName));
            BufferedReader bufReader = new BufferedReader(inputReader);
            String line = "";
            String Result = "";
            while ((line = bufReader.readLine()) != null)
                Result += line;
            return Result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

Gson解析復(fù)雜json的數(shù)據(jù)。

JsonParse:

通過(guò)getAsJsonObjectgetAsJsonArray解析成JsonObject和JsonArray。

JsonElement抽象類。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.概述2.Gson的目標(biāo)3.Gson的性能和擴(kuò)展性4.Gson的使用者5.如何使用Gson 通過(guò)Maven來(lái)使用...
    人失格閱讀 14,557評(píng)論 2 18
  • 【Android 庫(kù) Gson】 引用: ★Gson 解析教程★★★ Gson的入門使用Gson全解析(上)-Gs...
    Rtia閱讀 3,096評(píng)論 0 9
  • 以前我對(duì)于寵物狗是沒(méi)有感覺(jué)的,因?yàn)槲壹以卩l(xiāng)下,家人不允許養(yǎng)任何沒(méi)有應(yīng)用價(jià)值的動(dòng)物,所以我只可以看見(jiàn)能裝進(jìn)肚子里的雞...
    九汝竹書(shū)閱讀 510評(píng)論 5 1
  • 婆媳關(guān)系,無(wú)論你是家財(cái)萬(wàn)貫還是吃了幾十年狗糧的單身狗,你都正在或者即將遇到這個(gè)問(wèn)題。這個(gè)問(wèn)題處理好了,雞犬升天,處...
    煒安Vivian閱讀 648評(píng)論 0 0
  • 昨天工作上出了一點(diǎn)問(wèn)題,讓我充分意識(shí)到,人不能懶散!任何你負(fù)責(zé)的事情,都是另一個(gè)人對(duì)你的信任。不要辜負(fù)這種信任,今...
    懶大叔閱讀 288評(píng)論 0 0

友情鏈接更多精彩內(nèi)容