筆者前幾周在處理數(shù)據(jù)解析這塊碰到了好多的坑
這里只討論數(shù)據(jù)解析這塊的知識
這里并不打算直接通過object = new Gson().fromJson(json, object.getClass());得到對應(yīng)的json的實體類型
而是通過JsonParser Api對數(shù)據(jù)進行解析,方便后面講到對于復(fù)雜特殊的json串進行解析

通過上圖的代碼片段可以清晰的看到對于一個json串,使用JsonParser api解析后,它就是一個JsonElement對象了,但是這個JsonElement到底是什么,對應(yīng)的到底是哪一類呢,看了代碼可以知道,總共就四類,JsonNull(空串這樣的),JsonObject,JsonArray,JsonPrimitive,相信接觸過json的同學(xué)對JsonObject,JsonArray很熟悉了吧,用的最多的就是這兩個,JsonNull用的少,JsonPrimitive估計都沒有聽過吧
JsonNull沒什么好講的,自己做實驗就知道了,JsonPrimitive表示的是json串里面的內(nèi)容是基礎(chǔ)類型,可以看類的定義

當(dāng)然了也存在特殊的情況,它也是JsonPrimitive類型
我們再看一段代碼片段
定義了一個string變量
String json = "{\"code\":200, \"message\":\"ok\", \"data\":\"{\\\"id\\\":131,\\\"appId\\\":6,\\\"versionCode\\\":6014000}\"}";

我們需要關(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)一些莫名其妙的問題
舉一個例子來描述這種場景:

這個代碼片段試將后端的一個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);
}