Gson

Версия Minecraft
1.7.10

mayakplay

SpringFlomaster
217
3
160

deleted.user

Мошенник
321
43
Возможно, будет полезно. Но у меня с этим кодом сейчас есть проблемы, вроде того, что типы теряются (Integer становится String, а ItemStack - LinkedTreeMap)
Код:
public class JsonItemStack
        implements JsonSerializer<ItemStack>,
        JsonDeserializer<ItemStack> {
   public static final Type TYPE = new TypeToken<ItemStack>(){}.getType();

   public ItemStack deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
      JsonObject object = json.getAsJsonObject();
      GameRegistry.UniqueIdentifier id = new GameRegistry.UniqueIdentifier(object.get("item").getAsString());
      ItemStack stack = GameRegistry.findItemStack((String)id.modId, (String)id.name, (int)(object.has("stacksize") ? object.get("stacksize").getAsInt() : 1));
      if (stack == null) {
         String info = "Invalid item: " + json.toString();
         ArrayList<String> lore = new ArrayList<String>();
         ItemStack item = new ItemStack(Items.apple);
         lore.add("Name: " + object.get("item").getAsString());
         if (object.has("damage")) {
            lore.add("Count: " + object.get("damage").getAsInt());
         }
         LogManager.getLogger((String)"Daily Rewards 1.26b").log(Level.ERROR, info);
         ItemStackUtils.setStackDisplayNameAndLore(item, (Object)EnumChatFormatting.DARK_RED + "INVALID_ITEM", lore);
         return item;
      }
      if (object.has("damage")) {
         stack.setItemDamage(object.get("damage").getAsInt());
      }
      if (object.has("nbt")) {
         stack.stackTagCompound = (NBTTagCompound)context.deserialize(object.get("nbt"), JsonNBT.TYPE);
      }
      return stack;
   }

   public JsonElement serialize(ItemStack src, Type typeOfSrc, JsonSerializationContext context) {
      JsonObject object = new JsonObject();
      GameRegistry.UniqueIdentifier id = GameRegistry.findUniqueIdentifierFor(src.getItem());
      object.addProperty("item", id.toString());
      object.addProperty("stacksize", (Number)src.stackSize);
      object.addProperty("damage", (Number)src.getItemDamage());
      if (src.stackTagCompound != null) {
         object.add("nbt", context.serialize((Object)src.stackTagCompound));
      }
      return object;
   }

}

Код:
public class JsonNBT
        implements JsonSerializer<NBTBase>,
        JsonDeserializer<NBTBase> {
   public static final Type TYPE = new TypeToken<NBTBase>(){}.getType();

   public NBTBase deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
      if (json.isJsonNull()) {
         return null;
      }
      if (json.isJsonObject()) {
         NBTTagCompound compound = new NBTTagCompound();
         JsonObject object = json.getAsJsonObject();
         for (Map.Entry entry : object.entrySet()) {
            NBTBase nbtBase = (NBTBase)context.deserialize((JsonElement)entry.getValue(), TYPE);
            compound.setTag((String)entry.getKey(), nbtBase);
         }
         return compound;
      }
      if (json.isJsonArray()) {
         NBTTagList nbtList = new NBTTagList();
         JsonArray jsonList = json.getAsJsonArray();
         for (JsonElement element : jsonList) {
            NBTBase nbtBase = (NBTBase)context.deserialize(element, TYPE);
            nbtList.appendTag(nbtBase);
         }
         return nbtList;
      }
      if (json.isJsonPrimitive()) {
         String string = json.getAsString();
         if (string.matches("[-+]?[0-9]*\\.?[0-9]+[d|D]")) {
            return new NBTTagDouble(Double.parseDouble(string.substring(0, string.length() - 1)));
         }
         if (string.matches("[-+]?[0-9]*\\.?[0-9]+[f|F]")) {
            return new NBTTagFloat(Float.parseFloat(string.substring(0, string.length() - 1)));
         }
         if (string.matches("[-+]?[0-9]+[b|B]")) {
            return new NBTTagByte(Byte.parseByte(string.substring(0, string.length() - 1)));
         }
         if (string.matches("[-+]?[0-9]+[l|L]")) {
            return new NBTTagLong(Long.parseLong(string.substring(0, string.length() - 1)));
         }
         if (string.matches("[-+]?[0-9]+[s|S]")) {
            return new NBTTagShort(Short.parseShort(string.substring(0, string.length() - 1)));
         }
         if (string.matches("[-+]?[0-9]+")) {
            return new NBTTagInt(Integer.parseInt(string.substring(0, string.length())));
         }
         if (string.matches("[-+]?[0-9]*\\.?[0-9]+")) {
            return new NBTTagDouble(Double.parseDouble(string.substring(0, string.length())));
         }
         if (!string.equalsIgnoreCase("true") && !string.equalsIgnoreCase("false")) {
            if (string.startsWith("[") && string.endsWith("]")) {
               if (string.length() > 2) {
                  String s = string.substring(1, string.length() - 1);
                  String[] astring = s.split(",");
                  try {
                     if (astring.length <= 1) {
                        return new NBTTagIntArray(new int[]{Integer.parseInt(s.trim())});
                     }
                     int[] aint = new int[astring.length];
                     for (int i = 0; i < astring.length; ++i) {
                        aint[i] = Integer.parseInt(astring[i].trim());
                     }
                     return new NBTTagIntArray(aint);
                  }
                  catch (NumberFormatException numberformatexception) {
                     return new NBTTagString(string);
                  }
               }
               return new NBTTagIntArray(new int[0]);
            }
            if (string.startsWith("\"") && string.endsWith("\"") && string.length() > 2) {
               string = string.substring(1, string.length() - 1);
            }
            string = string.replaceAll("\\\\\"", "\"");
            return new NBTTagString(string);
         }
         return new NBTTagByte((byte)(Boolean.parseBoolean(string) ? 1 : 0));
      }
      throw new JsonParseException("Invalid NBT: " + json.toString());
   }

   public JsonElement serialize(NBTBase src, Type typeOfSrc, JsonSerializationContext context) {
      if (src instanceof NBTBase.NBTPrimitive) {
         return new JsonPrimitive(src.toString());
      }
      if (src instanceof NBTTagString) {
         return new JsonPrimitive(((NBTTagString)src).func_150285_a_());
      }
      if (src instanceof NBTTagCompound) {
         NBTTagCompound compound = (NBTTagCompound)src;
         JsonObject object = new JsonObject();
         for (Object name : compound.func_150296_c()) {
            object.add((String)name, context.serialize((Object)compound.getTag((String)name)));
         }
         return object;
      }
      if (src instanceof NBTTagList) {
         NBTTagList list = (NBTTagList)src.copy();
         JsonArray array = new JsonArray();
         while (list.tagCount() != 0) {
            array.add(context.serialize((Object)list.removeTag(0)));
         }
         return array;
      }
      if (src instanceof NBTTagIntArray) {
         JsonArray array = new JsonArray();
         for (int val : ((NBTTagIntArray)src).func_150302_c()) {
            array.add((JsonElement)new JsonPrimitive((Number)val));
         }
         return array;
      }
      throw new IllegalArgumentException("Not supported by MC's JSON code. Type: " + src.getClass() + " Value: " + (Object)src);
   }

}
 
2,505
81
397
Ужасная реализация, конечно..
Имплементация TypeAdapter'а намного удобнее и красивее. И не нужно вот этих вот string.startsWith, Integer.parseInt и уж тем более string.matches.

Еще все инстансофы прекрасно заменяются на:
Kotlin:
when (nbtTag.id.toInt()) {
    NBT.TAG_BYTE  -> ...
    NBT.TAG_SHORT -> ...
    NBT.TAG_INT   -> ...
    ...
}

Чтобы не терять типы, можно к имени добавлять суффикс (.i, .f, .d, .s). Правда это сломается, если у тебя будет список разнотипных списков.
 
2,505
81
397
Но у меня с этим кодом сейчас есть проблемы, вроде того, что типы теряются (Integer становится String, а ItemStack - LinkedTreeMap)
Это не из-за твоего сериализатора.
Вангую, что ты хочешь хранить HashMap<Integer, ItemStack>. И при попытке чтения делаешь что-то типа
Java:
gson.fromJson(string, Map.class)
Но для дженерик объектов нужно использовать:
Java:
Type type = new TypeToken<HashMap<Integer, ItemStack>>(){}.getType();
gson.fromJson(string, type);
Тогда прочитается HashMap<Integer, ItemStack>. Но на самом деле не обычная хэш мапа, а особая gson'овская linked tree мапа. Если хочется именно обычная хэш мапа, то стоит зарегать InstanceCreator для простой хэш мапы.
 
Сверху