使用GSON反序列化嵌套对象

hc2pp10m  于 2022-11-06  发布在  其他
关注(0)|答案(4)|浏览(236)

我正在尝试反序列化以下结构

{ 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();

但是我得到一个解析错误,因为尝试反序列化Data而不是MetaData,我如何应用此反序列化程序使其正常工作?

2j4z5cfb

2j4z5cfb1#

我为我的类Data创建了一个反序列化程序,解决了这个问题。

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();

很明显,但有没有更优雅的解决方案?

bkhjykvo

bkhjykvo2#

首先,将类重命名为 meta而不是metadata,并将关键字设置为String而不是List,然后使用以下代码将JSonStringMap到对象。

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

为了只获取关键字,您需要这个。

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

keywords是一个JsonObject而不是一个JsonArray,所以你不能直接将它Map到List上。你可以将字符串拆分成数组中的keywords。

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

a2mppw5e3#

下面是一个简洁的解决方案,它利用Java继承来表示嵌套结构;因此不需要提供任何实际的示例成员字段(Map等)来捕获GSONMap的嵌套String数据。

**步骤1:**为了便于阅读,请创建一个空对象来表示嵌套Map

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

}

**第2步:*添加一行实际代码以进行Map; 没有其他序列化/反序列化逻辑要管理 *

protected void loadContent(JsonObject stateRegionsJsonObject) {

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

或者,您可以完全跳过 Package 器类,直接将<String, List<String>>放入GSON调用中。但是,我发现显式对象有助于通知/提醒正在阅读代码的任何人,其目的是什么。
JSON示例:
StateRegionCitiesMap表示一个多层Map结构,例如:
[US州] -〉[州-地区键] -〉[子地区键] -〉CitiesArray[]

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

alen0pnh4#

这样可以很容易地实现你想要的。你应该定义一个内部静态类。你可以保留嵌套类来定义关键字,比如类关键字等等。只要记住在包含类中有一个字段,比如在你的内部类中有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;
    }
}

相关问题