關(guān)于Gson解析的使用匯總

筆者前幾周在處理數(shù)據(jù)解析這塊碰到了好多的坑
這里只討論數(shù)據(jù)解析這塊的知識

這里并不打算直接通過object = new Gson().fromJson(json, object.getClass());得到對應(yīng)的json的實體類型

而是通過JsonParser Api對數(shù)據(jù)進行解析,方便后面講到對于復(fù)雜特殊的json串進行解析


image.png

通過上圖的代碼片段可以清晰的看到對于一個json串,使用JsonParser api解析后,它就是一個JsonElement對象了,但是這個JsonElement到底是什么,對應(yīng)的到底是哪一類呢,看了代碼可以知道,總共就四類,JsonNull(空串這樣的),JsonObject,JsonArray,JsonPrimitive,相信接觸過json的同學(xué)對JsonObject,JsonArray很熟悉了吧,用的最多的就是這兩個,JsonNull用的少,JsonPrimitive估計都沒有聽過吧

JsonNull沒什么好講的,自己做實驗就知道了,JsonPrimitive表示的是json串里面的內(nèi)容是基礎(chǔ)類型,可以看類的定義

image.png

當(dāng)然了也存在特殊的情況,它也是JsonPrimitive類型

我們再看一段代碼片段
定義了一個string變量

String json = "{\"code\":200, \"message\":\"ok\", \"data\":\"{\\\"id\\\":131,\\\"appId\\\":6,\\\"versionCode\\\":6014000}\"}";
image.png

我們需要關(guān)注的是json串里面key為“data”所對應(yīng)的value,應(yīng)該看得比較清楚,data的內(nèi)容都帶有轉(zhuǎn)義符號,那么我們該怎么解析這樣的數(shù)據(jù)呢?

回答問題前,我們看看這段代碼的執(zhí)行結(jié)果,最終輸出的是

json == {"code":200, "message":"ok", "data":"{\"id\":131,\"appId\":6,\"versionCode\":6014000}"}
isJsonObject
isJsonPrimitive == true

可以看到data的內(nèi)容就是一個jsonPrimitive類型的,因為它在后端處理的時候,就將真實的內(nèi)容給拍平了(不知道能不能用序列化描述額,總之是被轉(zhuǎn)義了,看起來就不是一個json串,而變成了一個純粹的string)

那么在我們解析這個被轉(zhuǎn)義的字符串的時候,需要把轉(zhuǎn)義符號去掉。

JsonPrimitive primitive = jsonElement.getAsJsonObject().get("data").getAsJsonPrimitive();
System.out.println("getAsString == " + primitive.getAsString());
System.out.println("toString == " + primitive.toString());            

得到的結(jié)果是

getAsString == {"id":131,"appId":6,"versionCode":6014000}
toString == "{\"id\":131,\"appId\":6,\"versionCode\":6014000}"

看這個執(zhí)行結(jié)果可以知道通過getAsString(),得到的就是一個json串,而不是還帶有轉(zhuǎn)義字符的string,這種情況下,就可以通過
App app = new Gson().fromJson(primitive.getAsJsonPrimitive().getAsString(), App.class);得到具體的實體類模型了

以上只是簡單的情況,復(fù)雜的情況需要結(jié)合真實的實際場景來,使用標(biāo)準(zhǔn)的Gson api解析,這樣可以避免出現(xiàn)一些莫名其妙的問題

舉一個例子來描述這種場景:

image.png

這個代碼片段試將后端的一個json數(shù)據(jù)轉(zhuǎn)換成了map的數(shù)據(jù)結(jié)構(gòu),我們看下結(jié)果

{code=200.0, message=ok, data=dataString}

發(fā)現(xiàn)code被轉(zhuǎn)成了200.0,變成了double類型,這個問題在這里不深究,想深究的可以看這個https://gist.github.com/xingstarx/5ddc14ff6ca68ba4097815c90d1c47cc,以及https://stackoverflow.com/a/36529534/5279354 總之在使用Gson解析的時候,不要只知道gson.from這一個api,沒事也需要多看看Gson相關(guān)的其他api,了解下Gson解析的工作原理,有助于我們更好的處理這類問題

附上完整的代碼片段

@Test
    public void test2() {
        String json = "{\"code\":200, \"message\":\"ok\", \"data\":\"{\\\"id\\\":131,\\\"appId\\\":6,\\\"versionCode\\\":6014000}\"}";
        System.out.println("json == " + json);

        JsonElement jsonElement = new JsonParser().parse(json);
        if (jsonElement.isJsonNull()) {
        } else if (jsonElement.isJsonObject()) {
            JsonPrimitive primitive = jsonElement.getAsJsonObject().get("data").getAsJsonPrimitive();
            System.out.println("getAsString == " + primitive.getAsString());
            System.out.println("toString == " + primitive.toString());
            App app = new Gson().fromJson(primitive.getAsJsonPrimitive().getAsString(), App.class);
//            App app = new Gson().fromJson(primitive.getAsJsonPrimitive().toString(), App.class);
            System.out.println(app);
        } else if (jsonElement.isJsonArray()) {
        } else if (jsonElement.isJsonPrimitive()) {
        }

//        Map<String, Object> map = new LinkedTreeMap<>();
//        map = new Gson().fromJson(json, map.getClass());
//        System.out.println(map);
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容