1

I'm using GSON to deserialize my JSON string. It seems to choke when attempting to deserialize a 2D array of objects. Here's the bit:

{ .
  ..
  ...
  "states": [
            {"SPAWNINGPHASE": [{"name": "STATEA", "duration": 4}, {"name": "STATEB", "duration": 4}]},
            {"ALIVEPHASE": [{"name": "STATEA", "duration": 5}, {"name": "STATEB", "duration": 4}]}
            ]
}

The above is a part of a bigger JSON. I get Expected BEGIN_ARRAY but was BEGIN_OBJECT I've looked over my JSON, but I don't see where it's incorrect

Group g=gson.fromJson(configFile, Group.class);

That's what I use to start the read. Is this not enough to process the string for the 2D array?

In Group.class I tried both

public State[][] states;

and

public List<List<State>> states;

Everything else seems to deserialize fine.

Do I have to use this (below)?

Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
0

1 Answer 1

1

The JSON you show has a field states.

That field holds an array which you show as holding two different types of objects. One has a field SPAWNINGPHASE, the other a field ALIVEPHASE. Each of those hold an array that contains another type of object.

This poses a problem for automatic deserailization to a POJO.

The only way that could possibly work is if your State class had fields for every "Phase" (This is assuming you have a Java class named NameAndDuration that you can map those inner objects to).

class State {
    List<NameAndDuration> SPAWNINGPHASE;
    List<NameAndDuration> ALIVEPHASE;
    ...
}

Provided you mean that your Group class represents the JSON object, it would have:

List<State> states;

Gson silently ignores any missing fields in the JSON, so what you'd end up with is a List of your State objects, with only one of those fields set and all the others null.

As-is you would need to have:

public List<Map<String, List<NameAndDuration>>> states; 

A JSON object is inherently a key/value map and since those objects inside the arrays are of a common type, that would work. You'd have a List containing Maps that each had one entry, the "phase" as the key and a list of those inner objects. Not exactly ideal, but it would work.

Option B and something that makes a little more sense is changing that JSON so the "phase" is a value:

{
    "states": [
        {
            "phase": "SPAWNINGPHASE",
            "values": [
                {
                    "name": "STATEA",
                    "duration": 4
                },
                {
                    "name": "STATEB",
                    "duration": 4
                }
            ]
        }
    ]
}

And change your State class accordingly:

class State {
    String phase;
    List<NameAndDuration> values;
}     

(Note you could also use an enum for phase here)

Now List<State> states; becomes a bit more usable. (Although it does seem a bit of a misnomer; it seems like you really have a list of "phases" that contain state info rather than a list of "states")

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, that was a great explanation. Option A worked for me, but I want to try Option B. It seems that it will be a little easier to work with in the long run.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.