1. 程式人生 > >json型別轉換

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資料,各有優勢吧。