Hey guys. So I'm currently working on a minigame, and when trying to use GSON to serialize (and deserialize) my Generator object which just generates items, I am getting a StackOverflowError. I've Googled to no avail, so am looking for help here. The problem is likely a dumb move from me, not making a field transient or something (although I'm using a manual TypeAdapter which shouldn't be affected by transient fields AFAIK). This is the error (repeats a couple of hundred times to fill up most of the console) Code (Text): at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:375) at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:380) at com.google.gson.internal.$Gson$Types.res [18:58:03 WARN]: olve($Gson$Types.java:375) at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:380) at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:375) at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:380) at com.google.gson.internal.$Gson$Types.resolve($Gson$Types.java:355) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:117) I know how to read a stack-trace, and from what I can tell it's nothing to do with my code, the closest piece of info I could find after Googling was that there's some sort of recursive field dependencies. Originally I was serializing the contents of my Locations class (which I still intend to do, I simply changed it for debugging), which has a Set of all the Generators. Same error as only serializing one generator. Also, these are the only fields in my Generator class so I don't think it's recursive dependencies: Code (Java): private final GeneratorType generatorType; private final Location[] locations; private final Location root; //* For serialization purposes private final boolean withHologram; private transient final AtomicInteger timeUntilEvolve; private transient final Placeholder time; private transient final Placeholder level; private transient AtomicInteger previousUpgradeTimes; private transient long timer; private GeneratorTier tier; private transient ScheduledFuture dropFuture; private transient Hologram h; Finally, here's the contents of my GeneratorSerializer class (YES it has been registered in GsonBuilder before you ask ): Spoiler Code (Java): public class GeneratorSerializer extends TypeAdapter<Generator> { public GeneratorSerializer() { super(); } @Override public void write(JsonWriter out, Generator value) throws IOException { out.beginObject(); if (value.isWithHologram()) { out.name("hologram").value(value.getH().getId()); } out.name("type").value(value.getGeneratorType().name()); out.name("root").value(Bedwars.getGson().toJson(value.getRoot())); // val locs = out.name("locations").beginArray(); // int x = 0; // locs.name(String.valueOf(x)).value(Bedwars.getGson().toJson(value.getLocations()[x])); // locs.endArray(); out.endObject(); out.flush(); out.close(); } @SuppressWarnings ("unchecked") @Override public Generator read(JsonReader in) throws IOException { in.beginObject(); Hologram hologram = null; GeneratorType type = null; Location root = null; String nextName; do { nextName = in.nextString(); switch (nextName.toLowerCase()) { case "hologram": String s = in.nextString(); hologram = Bedwars.getManager().getHologram(s); break; case "type": type = GeneratorType.valueOf(in.nextString()); break; case "root": root = Bedwars.getGson().fromJson(in.nextString(), Location.class); break; } } while (in.hasNext()); in.endObject(); in.close(); Validate.notNull(type, "GeneratorType"); Validate.notNull(root, "Root Location"); if (hologram == null) { return new Generator(root.getBlock(), type, false); } return new Generator(root.getBlock(), type, true); } } As always, any help would be massively appreciated (as this is incredibly annoying issue), so thanks guys
As far as I'm aware, this is due to Location not being GSON-friendly in terms of serialization. Keep in mind that Location holds a reference to World and GSON serializes all non-transient non-static fields... including the World. That's a lot of data. You're going to want to write a type adapter for World to serialize it as a name and deserialize it as a World from a name (Bukkit#getWorld(String)). See JsonSerializer<World> and JsonDeserializer<World>