繁体   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