您的位置:首页 > Web前端 > JavaScript

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

2017-04-24 10:20 615 查看

引言

在开发过程中,我们现在绝大部分都是使用
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": ...}


其中:

status
:返回状态

message
:返回消息

data
:返回数据

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

效果图:



解析

对于第一种和第二种
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
格式,由于
data
List
类型的,如果使用以上方式进行解析将无法得到
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);


项目地址 ☞ 传送门
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: