使用Gson自定义反序列化到Map中

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Gson自定义反序列化到Map中相关的知识,希望对你有一定的参考价值。

我有以下JSON:

{
    "abc": {
        "linkedTo": "count",
        // possibly more data...
    },
    "plmtq": {
        "linkedTo": "title",
        "decode": "true",
        // possibly more data...
    }
}

我需要将这个JSON加载到Map<String, Holder>中,密钥为"abc""plmtq"。 以下是我的Holder课程:

public class Holder {
  private final Map<String, String> data;

  public Holder(Map<String, String> data) {
    this.data = data;
  }

  // More methods in this class...
}

JSON与我的类结构不匹配,但我无法更改JSON或类。 我需要的是一种自定义反序列化的方法,以便我可以将JSON解析为Map<String, Holder>。 有没有办法做到这一点?


下面是执行该操作的代码,但它看起来太复杂了,必须有一个更简单的方法来执行它...

private static Map<String, Holder> getMap(String jsonLine)
{
    Map<String, Holder> holder = new HashMap<>();
    JsonElement jelement = new JsonParser().parse(jsonLine);
    JsonObject jobject = jelement.getAsJsonObject();

    for (Map.Entry<String, JsonElement> entry : jobject.entrySet())
    {
        Map<String, String> metadata = new HashMap<>();
        JsonObject element = entry.getValue().getAsJsonObject();

        for (Map.Entry<String, JsonElement> entry2 : element.entrySet())
        {
            metadata.put(entry2.getKey(), entry2.getValue().getAsString());
        }

        holder.put(entry.getKey(), new Holder(metadata));
    }
    return holder;
}
答案

如果你真的需要保持你的Holder类,我能想到的唯一选择是为你的Holder类创建一个自定义反序列化器。

通过这样做,每当你告诉Gson将一些JSON解析为Holder对象时,它将使用你的反序列化器,而不是“正常方式”(即将JSON键映射到对象属性)。

像这样的东西:

private class HolderDeserializer implements JsonDeserializer<Holder> {

  @Override
  public Holder deserialize(JsonElement json, Type type, JsonDeserializationContext context) 
    throws JsonParseException {

    Type mapType = new TypeToken<Map<String, String>>() {}.getType();
    Map<String, String> data = context.deserialize(json, mapType);

    return new Holder(data);
  }  
}

然后在创建Gson对象时注册反序列化器:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Holder.class, new HolderDeserializer());
Gson gson = gsonBuilder.create();

最后,你像这样解析你的JSON:

Type responseType = new TypeToken<Map<String, Holder>>() {}.getType();
Map<String, Holder> response = gson.fromJson(jsonLine, responseType);

您可以查看Gson的自定义(de)serializationthis other answer的文档,以获取更多信息......

注意:此评论已经过编辑,以便在评论/聊天中讨论后更清晰。

以上是关于使用Gson自定义反序列化到Map中的主要内容,如果未能解决你的问题,请参考以下文章

原始类型和数组的 GSON 自定义反序列化器

如何通过 gson 将 json 反序列化为嵌套的自定义地图?

Jackson 将 YAML 文件反序列化为 Map(没有自定义反序列化器)

完全理解Gson:Gson序列化

有啥方法可以使用 gson 反序列化 BigQuery Numeric 数据类型

HashMap(key,Object)中的Java Gson序列化和反序列化对象[重复]