Home > Software design >  Collection serialization issues
Collection serialization issues

Time:12-04

So my issue is a bit complex. I've got one User class, which I put into ConcurrentHashMap<String, User>. One class corresponds to one user. Key is user's ID.

I'm using GSON to serialize this ConcurrentHashMap and save the data of my users.

Inside of user class i have multiple variables (ints, Strings, etc.) and few Collections. Problem is in overwriting the file. 2 out of my 4 ArrayLists are serializing as usual, but when I add another ArrayList, or any collection for that matter, the collection won't show up in a file. However when I add a simple variable such as String or Int, the file updated and appends those values for every user. When new user is being created, those collections show up as nothing happened. I need to add those collections for already exsisting users.

My question is why in hell can't add another ArrayList to the class, and why it's not showing up in the file.

public class User {

private String nickname;
private String id;
private int coins;


  ...bunch of variables


private int bikes = 0;
private int scooters = 0;
private int goldIngots = 0;
private final ArrayList<Car> cars = new ArrayList<>(); //showing up
private final ArrayList<Hotel> hotels = new ArrayList<>(); //showing up
private final ArrayList<AwardType> awards = new ArrayList<>(); //not showing up   



...Constructor


...Getters And Setters

sample of UserClass

collections inside UserClass

how it should look

values are not appending

EDIT

AwardType is an enum. This list cointaining AwardType is not showing up for existing users, only for new ones.

EDIT 1

After adding Gson serializeNulls() option, the list is being added to the file but as a null.

"bikes": 0,
"scooters": 0,
"goldIngots": 0,
"cars": [],
"hotels": [],
"awards": null

CodePudding user response:

As mentioned in the comments you need to add a no-arg constructor (sometimes also called "default constructor") to your class. This constructor may be private (so you don't call it by accident).

This constructor is required for Gson to be able to create an instance and then afterwards update its field values during deserialization. Other constructors with parameters do not work because Gson cannot determine which JSON property matches which constructor parameter, and assuming default values (e.g. 0 and null) for the parameters might not be correct either in all situation.

If no no-arg constructor is detected Gson uses a specific JDK class called sun.misc.Unsafe to create an instance without calling any constructor and without executing any initializer block (including initializing fields). This can lead to issues such as the one you experienced. Additionally the Unsafe class might not be available in all environments. Due to this you should avoid relying on this behavior.

Alternatively you can also create an InstanceCreator for your class, but in most cases it is easier to add a no-arg constructor.

  • Related