De-serialising ItemStack's

Discussion in 'Spigot Plugin Development' started by kottalizer, Jul 8, 2015.

  1. kottalizer

    Supporter

    Yesterday I went to this forum regarding the best way to serialise the contents of a chest, and I ended up looping through the chest, running the serialize() method on all of its ItemStack's. Now I have successfully saved the contents of a chest in a MySQL table and I'd like to re-gain all of those ItemStacks.

    Basically, I now have a lot of one-liners looking like this:
    • {type=BEDROCK}
    • {type=DIAMOND_SWORD, meta=UNSPECIFIC_META:{meta-type=UNSPECIFIC, enchants={KNOCKBACK=2, DAMAGE_ALL=3}}}
    • {type=PORK, amount=2}
    • {type=WOOL}
    • {type=MUTTON}
    I have seen there are external libraries that could be used to de-serialise the content into Map<String, Object>, which in turn could easily be turned into ItemStack's, but what's the Spigot way of doing it?

    Question: What's the best practise when it comes to de-serialising single objects of ItemStack's?
     
  2. there is a matching deserialize method somewhere, dont have access to source atm, that takes the same Map result.
     
  3. kottalizer

    Supporter

    Yes, I'm thinking of using the deserialize() method, but in order to use that I somehow have to turn the plain String's into Map<String, Object>'s. I could probably use one of the many external libraries to accomplish that, but I'd like to know if there is a preferred Spigot way.
     
    • Creative Creative x 1
  4. I, for example, to serialize and deserialize I used this code:
    Code (Text):

    public static String itemsToString(ItemStack[] items) {
    try {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(serializeItemStack(items));
    oos.flush();
    return DatatypeConverter.printBase64Binary(bos.toByteArray());
    } catch (Exception e) {
    Logger.exception(e);
    }
    return "";
    }
    @SuppressWarnings("unchecked")
    public static ItemStack[] stringToItems(String s) {
    try {
    ByteArrayInputStream bis = new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(s));
    ObjectInputStream ois = new ObjectInputStream(bis);
    return deserializeItemStack((Map<String, Object>[]) ois.readObject());
    } catch (Exception e) {
    Logger.exception(e);
    }
    return new ItemStack[]{new ItemStack(Material.AIR)};
    }
    @SuppressWarnings("unchecked")
    private static Map<String, Object>[] serializeItemStack(ItemStack[] items) {
    Map<String, Object>[] result = new Map[items.length];
    for (int i = 0; i < items.length; i++) {
    ItemStack is = items[i];
    if (is == null) {
    result[i] = new HashMap<>();
    } else {
    result[i] = is.serialize();
    if (is.hasItemMeta()) {
    result[i].put("meta", is.getItemMeta().serialize());
    }
    }
    }
    return result;
    }
    @SuppressWarnings("unchecked")
    private static ItemStack[] deserializeItemStack(Map<String, Object>[] map) {
    ItemStack[] items = new ItemStack[map.length];
    for (int i = 0; i < items.length; i++) {
    Map<String, Object> s = map[i];
    if (s.size() == 0) {
    items[i] = null;
    } else {
    try {
    if (s.containsKey("meta")) {
    Map<String, Object> im = new HashMap<>((Map<String, Object>) s.remove("meta"));
    im.put("==", "ItemMeta");
    ItemStack is = ItemStack.deserialize(s);
    is.setItemMeta((ItemMeta) ConfigurationSerialization.deserializeObject(im));
    items[i] = is;
    } else {
    items[i] = ItemStack.deserialize(s);
    }
    } catch (Exception e) {
    Logger.exception(e);
    items[i] = null;
    }
    }
    }
    return items;
    }
    ./code]
     
    • Useful Useful x 1
  5. kottalizer

    Supporter

    Thanks for sharing!

    I have investigated a little further in this, and it seems like there is no ready-to-use method for de-serialising a serialised ItemStack from the JSON that the serialize() method provides, at least not without using external dependencies. For now I will stick to a solution similar to the one jakubzz suggested, as it in addition to be quite nifty should cover any new enchantments or equivalent changes that may occur to ItemStack in the future.
     
  6. you can use serialize & deserialize.

    but using custom nbt datas like custom heads, banners maybe?, maybe will cause errors, in my case, i was needing to make an api to "serialize" and deserialize, to store it in mysql.