简体   繁体   中英

How do I deserialize array of different types with GSON

First, I know there are many questions on this topic but I couldn't find one that solves my problem.

I need to deserialize with Gson a json that is in this form:

{
  "name": "abc",
  "entries":
  [
    [
      "first_entry_name",
      {"is_ok": true, "type": "first_entry_type"}
    ],
    [
      "second_entry_name",
      {"is_ok": false, "type": "second_entry_type"}
    ]
  ]
}

I've implemented the classes:

class Entries
{
    String name;
    ArrayList<Entry> entries;
}

class Entry
{
    String name;
    Details details;
}

class Details
{
    Boolean is_ok;
    String type;
}

I'm deserializing with:

Entries ent = new Gson().fromJson(json, Entries.class);

And I'm getting this error:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY

I understand why I'm getting this error but I can't think of a way to deserialize this json.

How should this json be deserialized?

Code is fine but your JSON file should be like below

 {
   "name": "abc",
   "entries":
   [
    {
      "first_entry_name":{"is_ok": true, "type": "first_entry_type"}
    },
    {
      "second_entry_name":{"is_ok": false, "type": "second_entry_type"}
    }
   ]
 }

In the json posted in original question, there was list inside a list (entries) but ideally it should be json element inside a list.

Here is the screenshot of code with output

在此处输入图片说明

Hope this helps

i am not really sure if that help , i come from c# world . but i think that will be a generic problem , so try to cast your instance (ent) from object to array or list of that Type ..

i mean like this

this c# syntax but i think there are mostly the same with java

<List>Entries ent = (<List>Entries)new Gson().fromJson(json, Entries.class);

it can be also here Array but List is more dynamic .. hopefully works

You may do something like below.

try adding another wrapper class as I have added sample here as EntryTwo.

class Entries
{
    String name;
    ArrayList<Entry> entries;
}

class Entry
{
   ArrayList<EntryTwo> entryTwo;

}
class EntryTwo
{
 String name;
 Details details;
}

class Details
{
    Boolean is_ok;
    String type;
}

Hope this works...

You need to implement custom deserialiser for List<Entry> type:

class EntriesJsonDeserializer implements JsonDeserializer<List<Entry>> {

    @Override
    public List<Entry> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonArray array = json.getAsJsonArray();
        List<Entry> entries = new ArrayList<>(array.size());
        for (JsonElement item : array) {
            JsonArray itemArray = item.getAsJsonArray();
            entries.add(parseEntry(context, itemArray));
        }

        return entries;
    }

    private Entry parseEntry(JsonDeserializationContext context, JsonArray array) {
        Entry entry = new Entry();
        entry.setName(array.get(0).getAsString());
        entry.setDetails(context.deserialize(array.get(1), Details.class));

        return entry;
    }
}

You can register it using JsonAdapter annotation:

class Entries {
    String name;

    @JsonAdapter(EntriesJsonDeserializer.class)
    List<Entry> entries;
}

You can try following code:

public class Entries {

    private String name;
    private List<List<String>> entries;
    public void setName(String name) {
         this.name = name;
     }
     public String getName() {
         return name;
     }

    public void setEntries(List<List<String>> entries) {
         this.entries = entries;
     }
     public List<List<String>> getEntries() {
         return entries;
     }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM