使用GSON和泛型解析约定格式的JSON字符串

引言

在开发过程中,我们现在绝大部分都是使用JSON格式进行数据交互,但是各个接口返回的数据内容不同,如果每个接口都进行GSON解析代码会显得比较臃肿。

背景

我们先来看一下JSON的几种基本格式:

# 第一种
{"status":0,"message":"成功","data":{"age":"15","sex":"女"}}
# 第二种
{"status":0,"message":"成功","data":{"name":"陌上花开","user":{"age":"15","sex":"女"},"list":[{"age":"15","sex":"女"},{"age":"15","sex":"男"}]}}
# 第三种
{"status":0,"message":"成功","data":[{"age":"15","sex":"女"},{"age":"15","sex":"男"}]}

经过分析,发现以上三种JSON字符串有一个共同的特点,JSON的结构一致:

{"status":0,"message":"成功","data": ...}

其中:

  1. status:返回状态
  2. message:返回消息
  3. data:返回数据

返回数据相同的JSON格式结构,因此如果定义一种通用的模型对应到此结构进行解析将会大大提高开发效率和代码简洁。但是值得注意的是data中的数据类型不一致,如:第一种包含的是简单对象,第二种包含的是对象中嵌套数组或对象,第三种包含的是List集合。所以针对data数据类型不一致的情况,我们可以使用泛型来解决。

效果图:
JSON解析

解析

对于第一种和第二种JSON格式的解析我们可以采用以下方式来进行:

public class Common<T> {

    private int status;
    private String message;
    private T data;

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

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

    public T getData() {
        return data;
    }

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

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

    public static Common fromJson(String json, Class clazz) {
        Gson gson = new Gson();
        Type objectType = type(Common.class, clazz);
        return gson.fromJson(json, objectType);
    }

    public String toJson(Class<T> clazz) {
        Gson gson = new Gson();
        Type objectType = type(Common.class, clazz);
        return gson.toJson(this, objectType);
    }

    static ParameterizedType type(final Class raw, final Type... args) {
        return new ParameterizedType() {
            public Type getRawType() {
                return raw;
            }

            public Type[] getActualTypeArguments() {
                return args;
            }

            public Type getOwnerType() {
                return null;
            }
        };
    }
}

对于第三种JSON格式,由于dataList类型的,如果使用以上方式进行解析将无法得到List<T>类型的class,所以针对第三种格式可以采用以下方式来进行:

public class CommonList<T> {

    private int status;
    private String message;
    private List<T> data;

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

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

    public List<T> getData() {
        return data;
    }

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

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

    public static CommonList fromJson(String json, Class clazz) {
        Gson gson = new Gson();
        Type objectType = type(CommonList.class, clazz);
        return gson.fromJson(json, objectType);
    }

    public String toJson(Class<T> clazz) {
        Gson gson = new Gson();
        Type objectType = type(CommonList.class, clazz);
        return gson.toJson(this, objectType);
    }

    static ParameterizedType type(final Class raw, final Type... args) {
        return new ParameterizedType() {
            public Type getRawType() {
                return raw;
            }

            public Type[] getActualTypeArguments() {
                return args;
            }

            public Type getOwnerType() {
                return null;
            }
        };
    }
}

使用

为了契合我们实际开发需求(实际开发过程中,我们往往会在封装好的方法中进行网络请求的数据解析),因此这里我们简单模拟实际情景进行接口封装,当然也会贴出直接使用的方式。

1.定义数据回调接口

public abstract class Callback<T> {

    public abstract void onSuccess(T t);

    public abstract T parseNetworkResponse(String str);
}

2.定义对象解析接口

public abstract class DataCallback<T> extends Callback<Common<T>> {

    @Override
    public Common<T> parseNetworkResponse(String str) {
        Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return Common.fromJson(str, entityClass);
    }
}

3.定义集合解析接口

public abstract class ListCallback<T> extends Callback<CommonList<T>> {

    @Override
    public CommonList<T> parseNetworkResponse(String str) {
        Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return CommonList.fromJson(str, entityClass);
    }
}

4.三种JSON格式的接口调用

# 第一种
DataUtil.getData(Constant.json1, new DataCallback<UserBean>() {

        @Override
        public void onSuccess(Common<UserBean> userCommon) {

        }
    });

# 第二种
DataUtil.getData(Constant.json2, new DataCallback<PersonBean>() {

        @Override
        public void onSuccess(Common<PersonBean> userCommon) {

        }
    });

# 第三种
DataUtil.getData(Constant.json3, new ListCallback<UserBean>() {

        @Override
        public void onSuccess(CommonList<UserBean> userCommonList) {

        }
    });

5.三种JSON格式的直接调用

# 第一种
Common<UserBean> user = Common.fromJson(Constant.json1, UserBean.class);

# 第二种
Common<PersonBean> person = Common.fromJson(Constant.json2, PersonBean.class);

# 第三种
CommonList<UserBean> users = CommonList.fromJson(Constant.json3, UserBean.class);

项目地址 ☞ 传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值