簡體   English   中英

使用 GSON 反序列化嵌套對象

[英]Deserialize nested object with GSON

我正在嘗試反序列化以下結構

{ meta: { keywords:  [a, b, c, d]}  ...  }

其他有效結構是

{ meta: { keywords: "a,b,c,d"}  ... }

{ meta: {keywords: "a"}  ...}

我有這門課

public class Data {
   @PropertyName("meta")
   MetaData meta;
   ...
}


public class  MetaData {
    List<String> keywords;
    ...
}

和一個自定義解串器

public static class CustomDeserilizer implements JsonDeserializer<MetaData>{
    @Override
    public MetaData deserialize(JsonElement json, Type typeOfT,  JsonDeserializationContext context) throws JsonParseException {
        List<String> keywords = null;
        Gson gson = new Gson();
        MetaData metaData = gson.fromJson(json, AppMetaData.class);
        JsonObject jsonObject = json.getAsJsonObject();

        if (jsonObject.has("keywords")) {
            JsonElement elem = jsonObject.get("keywords");
            if (elem != null && !elem.isJsonNull()) {

                if (jsonObject.get("keywords").isJsonArray()) {
                    keywords = gson.fromJson(jsonObject.get("keywords"),   new TypeToken<List<String>>() {
                    }.getType());
                } else {
                    String keywordString = gson.fromJson(jsonObject.get("keywords"), String.class);
                    keywords = new ArrayList<String>();
                    list.addAll(Arrays.asList(keywordString.split(",")));
                }
            }
        }
       metaData.setKeywords(keywords);
}

然后我嘗試應用脫硫劑:

Gson gson = new GsonBuilder()              
        .registerTypeAdapter(Data.class,new CustomDeserilizer())               
        .create();

但是我得到一個解析錯誤,因為試圖反序列化數據而不是元數據,我怎樣才能應用這個反序列化器來使它正常工作?

我解決了它,為我的數據類創建了一個反序列化器。

public static class DataDeserilizer implements JsonDeserializer {
    @Override
    public Data deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        Gson gson = new Gson();
        Data data = gson.fromJson(json, Data.class);
        JsonObject jsonObject = json.getAsJsonObject();
        if (jsonObject.has("meta")) {
            JsonElement elem = jsonObject.get("meta");
            if (elem != null && !elem.isJsonNull()) {

                Gson gsonDeserializer = new GsonBuilder()
                        .registerTypeAdapter(MetaData.class, new CustomDeserilizer())
                        .create();
                gsonDeserializer.fromJson(jsonObject.get("meta"), Data.class);
            }
        }

        return data;
    }



}

Gson gson = new GsonBuilder()              
    .registerTypeAdapter(Data.class,new DataDeserilizer())               
    .create();

很明顯,但是有更優雅的解決方案嗎?

首先,將您的類重命名為 meta 而不是 metadata 並使關鍵字 String 而不是 List。然后使用以下內容將您的 JSonString 映射到您的對象中。

Gson gson = new GsonBuilder().create();
Meta meta = gson.from(yourJsonString,Meta.class);

為了僅獲取關鍵字,您需要這個。

JsonObject jsonObject = new JsonObject(yourJSonString);
String data = jsonObject.getJsonObject("meta").getString("keywords");

關鍵字是 JsonObject 而不是 JsonArray,因此您不能直接將其映射到 List。 您可以拆分字符串以獲取數組中的關鍵字。

String keywords[] = data.split(",");

這是一個簡潔的解決方案,它利用 Java 繼承來表示嵌套結構; 因此不需要提供任何實際的實例成員字段(映射等)來捕獲 GSON 映射的嵌套String數據。

第 1 步:為了可讀性,創建一個空對象來表示嵌套映射

public class StateRegionCitiesMap extends HashMap<String, List<String>> {

}

第二步:添加一行實際代碼做映射; 無需管理其他序列化/反序列化邏輯

protected void loadContent(JsonObject stateRegionsJsonObject) {

    HashMap<String, StateRegionCitiesMap> stateRegionCitiesMap =
            mGson.fromJson(
                    stateRegionsJsonObject,
                    new TypeToken<HashMap<String, StateRegionCitiesMap>>() {
                    }.getType()
            );
}

或者,您可以完全跳過包裝類,直接將<String, List<String>>放入 GSON 調用中。 但是,我發現一個明確的對象有助於通知/提醒正在閱讀代碼的人,目的是什么。


示例 JSON:

StateRegionCitiesMap類表示多層地圖結構,例如:

[US State] -> [State-Region Key] -> [Sub-Region Key] -> CitiesArray[]

"CA": {
  "Central CA": {
    "Central Valley": [
      "FRESNO",
      "VISALIA"
    ],
    "Sacramento Area": [
      "SACRAMENTO",
      "EL DORADO HILLS"
    ]
  },

這假設可以輕松實現您想要的。 您應該定義一個內部靜態類。 您可以保持嵌套類以將關鍵字定義為類關鍵字等。只要記住在包含類中有一個字段,即在您的內部類中有private Keywords keywords;

在您的主要課程中:

Gson gson = new Gson();
Data data = gson.fromJson(SOME_JSON_STRING, Data.class);

在一個名為 Data 的類中:

public class Data {
    private Meta meta;
    
    static class Meta{
        private String[] keywords;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM