Domanda

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);
È stato utile?

Soluzione

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")

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top