Saving PlayerData to restore it later

I want to create a plugin for a pvp-arena. If the player enters a join command, the data of the player gets saved. If he enters the leave command, the plugin will load the data. I want to save the inventory, the location, health, food, etc.
To serialize the Inventory, I used player.getInventory().poll() in a loop and saved every serialized Itemstack in a ArrayList. Then I saved the ArrayList as a File using an ObjectOutputStream.
To load the items, I used an ObjectInputStream to load the ArrayList. Then I iterated through the ArrayList, deserialized every ItemStack and offered it with player.getInventory().offer(stack).

public static String serializeItemStack(ItemStack item) {
	try {
		StringWriter sink = new StringWriter();
		GsonConfigurationLoader loader = GsonConfigurationLoader.builder().setSink(() -> new BufferedWriter(sink)).build();
		ConfigurationNode node = loader.createEmptyNode();
		node.setValue(TypeToken.of(ItemStack.class), item);
		loader.save(node);
		return sink.toString();
	} catch (Exception e) {
		e.printStackTrace();
		return null;
	}
}
public static ItemStack deserializeItemStack(String json) {
	try {
		StringReader source = new StringReader(json);
		GsonConfigurationLoader loader = GsonConfigurationLoader.builder().setSource(() -> new BufferedReader(source)).build();
		ConfigurationNode node = loader.load();
		return node.getValue(TypeToken.of(ItemStack.class));
	} catch (Exception e) {
		e.printStackTrace();
		return null;
	}
}

This works, but if the player has an enchanted item, I get a NullPonterException when creating the StringReader, so the ArrayList seems to contain null where the enchanted item should be.
Does anybody have an idea to fix this or a better way to do this?

ItemStacks have a much better way of being serialized: ItemStack#toContainer(). This will include the items type, amount, and well as any DataManipulators - whether they are vanilla (enchantments, extra data, etc) or custom (eg a plugin’s “levelled” items).

You can then use ConfigurateTranslator to serialize that to a Configurate node. There’s a configurate module for gson, GsonConfigurationLoader.

To deserialize, Get the DataContainer with the loader, and then ConfigurateTranslator again. From there, you can get a ItemStack instance with Sponge.getDataManager().deserialize(ItemStack.class, myData).

This system can be used for many of Sponge’s objects, and is very modular.