1

I want to save an array of Mission.class which have variables as follows:

public class Mission {

public MissionEnum missionEnum;
public int progress;

public Mission(MissionEnum missionEnum, int progress) {
    this.missionEnum = missionEnum;
    this.progress = progress;
}

and also save missions in another java class:

public void saveMissions() {
    Json json = new Json();
    json.setOutputType(JsonWriter.OutputType.json);
    json.addClassTag("Mission", Mission.class);
    FileHandle missionFile = Gdx.files.local("missions_array.json");
    missionFile.writeString(json.prettyPrint(missions), false);
}

and load missions:

public void loadMissions() {
    if (Gdx.files.local("missions_array.json").exists()) {
        try {
            FileHandle file = Gdx.files.local("missions_array.json");
            Json json = new Json();
            json.addClassTag("Mission", Mission.class);
            missions = json.fromJson(Array.class, Mission.class, file);
            for (Mission mission : missions) {
                Gdx.app.log(TAG, "Mission loaded: " + mission.missionEnum);
            }
            Gdx.app.log(TAG, "Load missions successful");
        } catch (Exception e) {
            Gdx.app.error(TAG, "Unable to read Missions: " + e.getMessage());
        }
    }
}

I got json like this:

[
{
"class": "Mission",
"missionEnum": "BUY_POWERUP"
},
{
"class": "Mission",
"missionEnum": "DISTANCE_ONE_RUN_2"
},
{
"class": "Mission",
"missionEnum": "BANANA_TOTAL_2",
"progress": 35
}
]

However when loadMissions() is run I got the "Load missions successful" log shown but "Mission loaded..." aren't shown without any error log. Missions appeared not loaded properly. I do not know what went wrong because another array is loaded successful the same way.

lamma
  • 31
  • 5
  • Is it possible that the missing progress field in some missions creates the issue? What error logs are shown? Perhaps adding a constructor with only a Mission Enum and setting the progress to zero solves it. – albodelu Aug 12 '16 at 18:08
  • I have reverted back to preferences. nvm – lamma Aug 14 '16 at 22:26

2 Answers2

1

Updated response:

Add an empty contructor and read this and this

You will either have to add a no-argument constructor to (Mission), or you will have to add a custom serializer (see https://code.google.com/p/libgdx/wiki/JsonParsing#Customizing_serialization) that knows how to save a (Mission) instance and knows the appropriate constructor to invoke when reading a (Mission) back in.

public Mission() {
    // Do nothing.
}

Reading & writing JSON

The class implementing Json.Serializable must have a zero argument constructor because object construction is done for you.

Alternatively delete the unused constructor. I think Enigo answer is also correct so I'm going to upvote his answer.

Providing Constructors for Your Classes

You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors. This default constructor will call the no-argument constructor of the superclass. In this situation, the compiler will complain if the superclass doesn't have a no-argument constructor so you must verify that it does. If your class has no explicit superclass, then it has an implicit superclass of Object, which does have a no-argument constructor.

Note: I didn't test our responses, I have not developed games or used libgdx in the last two years.

Also read this libgdx issue: Json - constructor default value with Enum:

I don't know if this would be called a bug but, I have a case where I have an enum like this;

Then I have a class with 2 constructors;

This second gets called by my framework, the first by Json deserialization.

...

Previous response:

I guess that the missing progress field in some Mission classes can be the source of the issue but would be interesting to read the error logs to be sure.

I followed this, this and this to confirm this but it's hard without extra information about the exact log error.

Hasen
  • 11,710
  • 23
  • 77
  • 135
albodelu
  • 7,931
  • 7
  • 41
  • 84
1

Not sure why there are no errors in the logs, since while reproducing your problem I've got an exception.

The problem is in loadMissions() method: you create new Json parser without setting the class tag:

Json json = new Json();
// add the line below
json.addClassTag("Mission", Mission.class);
missions = json.fromJson(Array.class, Mission.class, file);
....

Without the tag parser doesn't know what is "class": "Mission" in json file.

Update

Another thing that may cause this issue is the args-constructor. At least, when I added it I got an exception. If you don't use it - just delete. Still, quite weird that you don't have any exceptions in logs'cos I definitely have.

Enigo
  • 3,685
  • 5
  • 29
  • 54
  • Actually I didn't use addClassTag also for saveMission but I still get the same problem. Just didn't want to show the package yet. Thank now I know I need addClassTag in both method. It doesn't solve the problem though. – lamma Aug 12 '16 at 22:49
  • I added class tag to the question – lamma Aug 12 '16 at 23:10