jefftherobot
jefftherobot

Reputation: 3

Parse dynamic json key at root with Retrofit 2

I'm having trouble parsing some json that is simple, albeit the root key is dynamic. I know from the other answers here I need to use a map, but it doesn't work. How do I use a map for the root element?

The JSON is always one root key with one array list:

Example 1

{
  "publishers": [
      "America's Best Comics",
      "DC Comics",
      "Devil's Due",
      "IDW Publishing",
      "Image",
      "Kodansha",
      "Oni Press",
      "Valiant",
      "Vertigo"
  ]
}

Example 2

{
  "series": [
      "All-Flash Quarterly",
      "Flash Annual",
      "Flash Comics",
      "Green Arrow",
      "Green Lantern",
      "Impulse",
      "The Flash",
      "The Flash Annual",
      "Wonder Woman"
  ]
}

Model:

public class EntityList {
    private Map<String, List<String>> entities;

    public Map<String, List<String>> getEntities() {
        return entities;
    }

    public void setEntities(Map<String, List<String>> entities) {
        this.entities = entities;
    }

}

Relevant parts of Retrofit call:

call.enqueue(new Callback<EntityList>() {

    @Override
    public void onResponse(Call<EntityList> call, Response<EntityList> response) {
        if(response.isSuccessful()){

            Map<String, List<String>> entityList= response.body().getEntities();

            for (String mapKey :  maps.keySet()) {
                Log.d("Map","mapKey : "+mapKey+" , mapValue : "+maps.get(mapKey));
            }


        } else {
            ...
        }
    }

Upvotes: 0

Views: 1347

Answers (1)

iagreen
iagreen

Reputation: 32016

Your top level is a Map, but you are trying to deserialize and object containing a map. Get rid of the EntityList class and use Map<String, List<String>> as your target.

call.enqueue(new Callback<EntityList>() {

    @Override
    public void onResponse(Call<Map<String, List<String>>> call, Response<Map<String, List<String>>> response) {
        if(response.isSuccessful()){

            Map<String, List<String>> entityList = response.body();

            for (String mapKey :  maps.keySet()) {
                Log.d("Map","mapKey : "+mapKey+" , mapValue : "+maps.get(mapKey));
            }


        } else {
            ...
        }
    }

You will need to update your interface to return Call<Map<String, List<String>>> as well.

Upvotes: 2

Related Questions