亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

具有抽象類的多映射的 Gson 反序列化

具有抽象類的多映射的 Gson 反序列化

牧羊人nacy 2022-01-19 16:54:57
我一生都無法弄清楚如何反序列化:{  "c8147c8a-09c3-4165-b5c2-ce72e2c97100": {    "pets": {      "BOOST": [        {          "mcmmoBoost": 15.0,          "owner": "c8147c8a-09c3-4165-b5c2-ce72e2c97100",          "entityType": "IRON_GOLEM",          "health": 150.0,          "tier": 1,          "alive": true        }      ]    },    "uuid": "c8147c8a-09c3-4165-b5c2-ce72e2c97100"  }}進入一個Map<UUID, PetPlayer>帶有 PetPlayer 的包含一個名為“pets”的多圖,其結構如下;Multimap<PetType, Pet>. PetType 在這里是一個枚舉,而 Pet 是一個具有多個實現的抽象類。我嘗試使用這兩個序列化器和反序列化器。第一:public final class HashMultimapAdapter implements JsonSerializer>, JsonDeserializer> { private static final PetAdapter petAdapter = new PetAdapter();    @Override    public JsonElement serialize(Multimap<PetType, Pet> src, Type typeOfSrc, JsonSerializationContext context) {        return context.serialize(src.asMap());    }    @Override    public Multimap<PetType, Pet> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {        Map<PetType, Collection<JsonElement>> asMap = context.deserialize(json, new TypeToken<Map<PetType, Collection<JsonElement>>>(){{}}.getType());        Multimap<PetType, Pet> multimap = ArrayListMultimap.create();        for (Map.Entry<PetType, Collection<JsonElement>> entry : asMap.entrySet()) {            entry.getValue().forEach(jsonElement -> {                multimap.put(entry.getKey(), petAdapter.deserialize(jsonElement, Pet.class, context));            });        }        return multimap;    }}這導致了堆棧溢出。java.lang.StackOverflowError    at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:375) ~[PaperSpigot-1.8.8-R0.1.jar:git-PaperSpigot-"4c7641d"]我非常感謝任何幫助:)
查看完整描述

1 回答

?
青春有我

TA貢獻1784條經驗 獲得超8個贊

我真的不知道在沒有手動或hacky的情況下使用gson執行此操作的方法。這太大了,無法作為評論發表,因此我將其留在這里作為答案,以幫助您解決問題。


首先,您會遇到堆棧溢出,因為您正在調用context.deserialize相同的參數,這些參數觸發gson調用相同的反序列化器,它將再次調用context.deserialize,依此類推,直到堆棧溢出。


序列化時你會遇到同樣的問題,因為你也只是在做context.serialize.


為避免這種情況,您需要避免gson遞歸調用序列化器/反序列化器的方法。這很容易通過創建另一個gson沒有適配器的實例來實現:


public class PetAdapter 

           implements JsonSerializer<Pet>, JsonDeserializer<Pet> {

  private final Gson gson = new Gson();


  @Override

  public Pet deserialize(JsonElement jsonElement, Type typeOfT, 

      JsonDeserializationContext context) throws JsonParseException {

     EntityType entityType = EntityType.valueOf(jsonElement.getAsJsonObject().get("entityType").getAsString());


      switch (entityType) {

        case IRON_GOLEM:

            return gson.fromJson(jsonElement, EcoPet.class);

        case WOLF:

            return gson.fromJson(jsonElement, BoostPet.class);

        case MAGMA_CUBE:

            return gson.fromJson(jsonElement, CombatPet.class);

        default:

            throw new JsonParseException("Invalid PetType");

      }

  }


  @Override

  public JsonElement serialize(Pet src, Type typeOfSrc, JsonSerializationContext context) {

    return gson.toJson(src);

  }

}

這有效,但前提是您的Pet實現不依賴于其他自定義序列化器/反序列化器。所以你可以想象這很hacky。


另一種方法是手動反序列化。這意味著您必須通過 json 元素并讀取屬性,就像您正在閱讀entityType和手動構建您的對象一樣。


非常相似,我想(我沒有檢查這個),您可以首先context將每個寵物反序列化為一個Map對象,并讓每個寵物實現一個靜態方法,該方法從該地圖創建特定寵物的實例。就像是:


public class IronGolem extends Pet {

   public static IronGolem from(Map<String, Object> deserializedPet) {

      // here check the map for each thing you need

      return new IronGolem(/*pass in every attribute*/);

   }

}

希望這可以幫助。


查看完整回答
反對 回復 2022-01-19
  • 1 回答
  • 0 關注
  • 168 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號