json型別轉換
前言
在日常開發中,我們經常會用到json轉物件,或者物件轉json的情況,一般用到的就是阿里的Fastjson和谷歌的Gson。
本篇要說的是Gson中如何將json資料轉換為我們想要的資料型別。
1.json直接轉物件
我們一般的操作姿勢:
直接複製後臺下發的json,然後在Android Studio使用Gson外掛快捷生成實體類:
但是呢,有時候
這塊是一個模版json,我們在對資料做處理的時候,希望讓data給呼叫者自己去處理。通過傳入一個Class型別,來自動把我們data裡面的字串解析成對應的Class物件。
2.泛型化data資料體
public class ApiResultBean<T> { /** * msg : 獲取成功! * code : 200 * data : {} */ private String msg; private int code; private T data; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
這樣,我們可以把json中,我們需要處理的物件解析為 T型別。
然後在解析伺服器返回的json時,我們可以直接通過Gson進行解析:
ApiResultBean responseState = new Gson().fromJson(json, type);
我們看到,在進行解析時,需要傳入一個型別,例如:我們的T型別是一個Movie電影列表資訊,則可以這樣寫:
new TypeToken<ApiResultBean<List<MovieBean>>>(){}.getType();
這裡的T = List<MovieBean>,這樣我們的資料就能正常處理成功了。
如果是一個字串型別則是T = String
new TypeToken<ApiResultBean<String>>(){}.getType();
但是,使用這種方式的前提是,我們在呼叫後臺API的時候,明確知道,返回的T型別,而且型別是不變的。
例如,後臺在做後臺推送時,我們不知道後臺推送的json資料返回的data資料體是哪種T型別,這個時候,這種方式就無法使用了。
3.Gson型別介面卡
我們知道gson是可以自定義json型別解析的,實現方法如下:
public class ApiGsonBuilder { private static final GsonBuilder INSTANCE = new GsonBuilder(); static { INSTANCE.disableHtmlEscaping(); INSTANCE.registerTypeAdapter(MqttBaseMsgBean.class, new MqttMsgAdapter()); } public static Gson create() { return INSTANCE.create(); } }
第一步:禁用Html轉義;
第二步:註冊型別adapter,傳入我們的json實體類,和解析規則;
第三步:使用自定義的gson對json資料進行解析;
下面看下我們的type adapter,以 MqttBaseMsgBean 為例。
MqttBaseMsgBean 主要是根據下發的不同的cmd字串,來判斷需要傳入的T型別:
public class MqttBaseMsgBean implements Serializable {
/**
* id :
* ts : 323123213213
* nonce : xxx
* sign : xxx
* cmd : reboot
* data : {"code":"200","msg":"success"}
*/
private String id;
private String ts;
private String nonce;
private String sign;
private String cmd;
private String data;
public MqttBaseMsgBean() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTTs() {
return ts;
}
public void setTTs(String ts) {
this.ts = ts;
}
public String getNonce() {
return nonce;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getData() {
if (data == null) {
return "{}";
}
return data;
}
public void setData(String data) {
this.data = data;
}
}
我們看到data : {"code":"200","msg":"success"},是一個object物件,但是我們把它轉換成了String型別,這個時候,我們就可以拿到這個String data,然後在對這個字串進行解析了,只是比上面傳入T型別的方式多了一步型別轉換。
那麼,我們的MqttMsgAdapter.java,是怎麼解析的呢?
public class MqttMsgAdapter implements JsonDeserializer<MqttBaseMsgBean> {
public MqttBaseMsgBean deserialize(JsonElement json, Type type,
JsonDeserializationContext context)
throws JsonParseException {
MqttBaseMsgBean result = new MqttBaseMsgBean();
JsonObject jsonObject = json.getAsJsonObject();
JsonElement ret;
ret = jsonObject.get("id");
if (ret != null && !ret.isJsonNull()) {
result.setId(GsonHelper.getAsString(ret));
}
ret = jsonObject.get("ts");
if (ret != null && !ret.isJsonNull()) {
result.setTTs(GsonHelper.getAsString(ret));
}
ret = jsonObject.get("nonce");
if (ret != null && !ret.isJsonNull()) {
result.setNonce(GsonHelper.getAsString(ret));
}
ret = jsonObject.get("sign");
if (ret != null && !ret.isJsonNull()) {
result.setSign(GsonHelper.getAsString(ret));
}
ret = jsonObject.get("cmd");
if (ret != null && !ret.isJsonNull()) {
result.setCmd(GsonHelper.getAsString(ret));
}
ret = jsonObject.get("data");
if (ret != null && !ret.isJsonNull()) {
result.setData(ret.toString());
}
return result;
}
}
看到這裡,我們一下就清楚了,我們把所有的欄位都解析成了JsonElement,然後根據需求,將jsonElement轉換成我們需要的型別即可,如:
ret = jsonObject.get("data");
if (ret != null && !ret.isJsonNull()) {
result.setData(ret.toString());
}
這樣,我們就將data這個object型別轉換成了String型別,這樣第一次Gson解析就完成了。
當我們拿到cmd命令後,根據不同的cmd,就可以對String data 進行不同的轉換了:
MqttBaseMsgBean bodyBean = ApiGsonBuilder.create().fromJson(json, MqttBaseMsgBean.class);
if (bodyBean != null && !TextUtils.isEmpty(bodyBean.getCmd())) {
if (bodyBean.getCmd().equalsIgnoreCase("reboot")) {
ShellUtil.execShellReboot();
} else if (bodyBean.getCmd().equalsIgnoreCase("powerOff")) {
ShellUtil.execShellShutDown();
} else if (bodyBean.getCmd().equalsIgnoreCase("uploadLog")) {
MqttLogBean logBean = ApiGsonBuilder.create().fromJson(bodyBean.getData(), MqttLogBean.class);
if (logBean != null) {
uploadLog(context, bodyBean.getId(), logBean);
}
}
}
上面的程式碼中,我們將json轉換成了MqttBaseMsgBean物件,然後判斷cmd命令是reboot,還是powerOff,還是updataLog?三種類型的命令,來判斷我們需要把data字串,是解析成MqttLogBean,還是直接執行關機或重啟動作。
這樣就完成了整個json資料的解析。
當然,你也可以使用FastJson來解析json資料,各有優勢吧。