android gson的使用

项目中一直使用的原生解析JSONObject.
参考链接https://www.jianshu.com/p/e740196225a4#
基于Gson V2.8.5

序列化: 把Java对象转换为字节序列的过程。 eg:toJson(对象)
反序列化:把字节序列恢复为Java对象的过程。eg:fromJson("字节序列",对象)

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 {}

基本数据类型的生成、

        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;
        ...

如果此时按照以下解析,哪怕try catch也拦截不到。

 /**
     * 从raw包下读取数据
     * @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 "";
    }
    

解析上面的报文。

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

//因为对应的为Object,所以这样的解析就会异常崩溃,并且拦截无用。
            JsonArray jsonArray = jsonParser.parse(response).getAsJsonArray();
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
        }
        String msg=jsonObject.get("msg").getAsString();
    }

错误日志如下:

     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)

然后实际开发中,后台返回的json格式可能跟我们要的不一致,如果线上的因为后台返回的数据格式而崩溃,哪怕最终查出原因是后台的问题,最终客户端还是得背锅,谁叫没有做容错处理呢。
如果服务端返回的为正确的数据解析方式:

    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的生成

将对象转换为字节序列的过程。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

将字节系列转为为对象的过程。fromJson

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

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

数组

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

List

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

@Expose、@SerializeName注解

json解析的字段(key)的名称和类型是一一对应的,当客户端和后台使用的语言不同,二者语言命名规范不同,命名规则常常不统一的情况下,使用@Expose和@SerializeName注解。
@Expose注解:区分实体中序列号的属性,包含两个属性,deserialize(反序列化)和serialize(序列化),默认为true。使用@Expose进行序列化,如果不想被序列化也可以使用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注解:属性重命名

//使用这样的方式创建gson对象。
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;

如果存在一个key多个写法,则可以选择@SerializeName的alternate别名的选择,根据以上代码可知为一个字符串数组。

借用例子
{"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
链接:https://www.jianshu.com/p/e740196225a4#

所以处理办法是:

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

多个情况同时存在时:
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
链接:https://www.jianshu.com/p/e740196225a4#

补充demo

image.png


如上图可以看到该json格式为外层JsonObject,里面有个key为rltInfo的JsonObject,rltInfo里面存在两个JsonArray的数组list.可以简易封装一下解析:

//基类
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客户端命名规则,shTaskList为服务端返回来的json的key
    @SerializedName("shTaskList")
    public List<T> mShTaskList;
}

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

    /**
     * 任务名称
     */
    private String taskName;

    /**
     * 所属用户ID
     */
    private String personId;

    /**
     * 所属用户名称
     */
    private String personName;

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

    /**
     * 门店名称
     */
    @SerializedName("orgName")
    private String storeName;

    /**
     * 区域ID
     */
    private String areaId;

    /**
     * 区域名称
     */
    private String areaName;

    /**
     * 任务开始时间-天
     */
    @SerializedName(value ="beginTimeStr",alternate={"submitTimeStr"})
    private String taskBeginDay;

    /**
     * 任务开始时间-时分秒
     */
    private String taskBeginHour;

    /**
     * 任务结束时间-天
     */
    @SerializedName("endTimeStr")
    private String taskEndDay;

    /**
     * 任务结束时间-时分秒
     */
    private String taskEndHour;

在Activity中解析数据:

   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包下读取数据
     *
     * @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解析复杂json的数据。

JsonParse:

通过getAsJsonObjectgetAsJsonArray解析成JsonObject和JsonArray。

JsonElement抽象类。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1.概述2.Gson的目标3.Gson的性能和扩展性4.Gson的使用者5.如何使用Gson 通过Maven来使用...
    人失格阅读 14,563评论 2 18
  • 【Android 库 Gson】 引用: ★Gson 解析教程★★★ Gson的入门使用Gson全解析(上)-Gs...
    Rtia阅读 3,129评论 0 9
  • 以前我对于宠物狗是没有感觉的,因为我家在乡下,家人不允许养任何没有应用价值的动物,所以我只可以看见能装进肚子里的鸡...
    九汝竹书阅读 523评论 5 1
  • 婆媳关系,无论你是家财万贯还是吃了几十年狗粮的单身狗,你都正在或者即将遇到这个问题。这个问题处理好了,鸡犬升天,处...
    炜安Vivian阅读 653评论 0 0
  • 昨天工作上出了一点问题,让我充分意识到,人不能懒散!任何你负责的事情,都是另一个人对你的信任。不要辜负这种信任,今...
    懒大叔阅读 289评论 0 0

友情链接更多精彩内容