I have a LinkedHashMap that contains two objects which both reside inside a normal HashMap. All 3 objects inside these maps have hashCode, equals, and toString methods. The "Chunk" object contains 3 variables a string and 2 integers all are final. The Location object only contains a string and 3 integers which are also final. Lastly, the ChestObject contains an enum and a list of other enums.
public static Map<Chunk, LinkedHashMap<Location, ChestObject>> CHEST_MAP = new HashMap<>();
public class Location {
private final String worldName;
private final int x;
private final int y;
private final int z;
public class Chunk {
private final String worldName;
private final int x;
private final int z;
public class ChestObject {
public List<Material> filteredMaterials = new ArrayList<>();
private ChestType chestType;
Saving the map works perfectly but retrieving the info throws the following error.
[17:17:53 WARN]: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 2 column 4 [17:17:53 WARN]:
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176) [17:17:53 WARN]:
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) [17:17:53 WARN]:
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:186) [17:17:53 WARN]:
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145) [17:17:53 WARN]:
at com.google.gson.Gson.fromJson(Gson.java:803) [17:17:53 WARN]:
at com.google.gson.Gson.fromJson(Gson.java:768) [17:17:53 WARN]:
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 2 column 4 [17:17:53 WARN]:
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:374) [17:17:53 WARN]:
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:165) [17:17:53 WARN]:
... 18 more
The file it attempts to read is the following...
{
"WorldName:world X:-3 Z:-64": {
"WorldName:world X:-39 Y:63 Z:-1016": {
"filteredMaterials": [
"ROTTEN_FLESH"
],
"chestType": "DOUBLE"
},
"WorldName:world X:-40 Y:63 Z:-1016": {
"filteredMaterials": [
"ROTTEN_FLESH"
],
"chestType": "DOUBLE"
}
}
}
The last bit of useful info is my recovery method which at this moment just attempts to print the map instead of assigning it to CHEST_MAP.
private void recoverChests() {
final File file = new File(getDataFolder(), "chests.json");
if(file.exists() && file.length() > 2) {
try {
final Gson gson = new GsonBuilder().setPrettyPrinting().create();
final Type type = new TypeToken<Map<Chunk, LinkedHashMap<Location, ChestObject>>>() {}.getType();
final Map<Chunk, LinkedHashMap<Location, ChestObject>> map = gson.fromJson(new FileReader(file), type);
System.out.println("Map: " + map);
} catch (IllegalStateException | JsonSyntaxException | IOException e) {
e.printStackTrace();
}
}
}
So based on the above error it appears that Json is having a hard time serializing object keys while it has no trouble doing the same for values. This is shown above since we can see Json saving the data as a String instead of an object like it did with our ChestObject. So how can I correctly save the above data so that Json correctly serializes key objects?
private void saveChests() {
try {
if(!CHEST_MAP.isEmpty()) {
final File file = new File(this.getDataFolder(), "chests.json");
final Gson gson = new GsonBuilder().setPrettyPrinting().create();
final Writer writer = new FileWriter(file);
gson.toJson(CHEST_MAP, writer);
writer.flush();
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}