Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing JSON with Retrofit and GSON, error when trying to parse and obtain callback.

I am using to Retrofit to handle Calls to my API for an Android Application. I am trying to get Retrofit to handle the parsing of the JSON, and creating a list of Objects in accordance with the POJO i have created.

The error i receive is "com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 176".

I used JsonSchema2Pojo to generate my java classes. The classes and associated JSON are as follows.

{"status":"success","data":[{"sort_key":1,"event_id":1947357,"title":"2014 US Open Tennis Session 15 (Mens\/Womens Round of 16)","datetime_utc":"2014-09-01T15:00:00","venue":{"city":"Flushing","name":"Louis Armstrong Stadium","extended_address":"Flushing, NY 11368","url":"https:\/\/seatgeek.com\/venues\/louis-armstrong-stadium\/tickets\/?aid=10918","country":"US","display_location":"Flushing, NY","links":[],"slug":"louis-armstrong-stadium","state":"NY","score":0.73523,"postal_code":"11368","location":{"lat":40.7636,"lon":-73.83},"address":"1 Flushing Meadows Corona Park Road","timezone":"America\/New_York","id":2979},"images":["https:\/\/chairnerd.global.ssl.fastly.net\/images\/performers-landscape\/us-open-tennis-45e2d9\/5702\/huge.jpg","https:\/\/chairnerd.global.ssl.fastly.net\/images\/performers\/5702\/us-open-tennis-c1ccf7\/medium.jpg","https:\/\/chairnerd.global.ssl.fastly.net\/images\/performers\/5702\/us-open-tennis-01f513\/large.jpg","https:\/\/chairnerd.global.ssl.fastly.net\/images\/performers\/5702\/us-open-tennis-4e07f2\/small.jpg"]}

From this i believe i need to generate 3 POJO's, my higher level "EventObject" Class, A Location Class, and a Venue Class. These classes and their variables follow:

EventObject Class:

public class EventObject {

private Integer sortKey;
private Integer eventId;
private String title;
private String datetimeUtc;
private Venue venue;
private List<String> images = new ArrayList<String>();
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

Location Class:

public class Location {

private Float lat;
private Float lon;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

Venue Class:

public class Venue {

private String city;
private String name;
private String extendedAddress;
private String url;
private String country;
private String displayLocation;
private List<Object> links = new ArrayList<Object>();
private String slug;
private String state;
private Float score;
private String postalCode;
private Location location;
private String address;
private String timezone;
private Integer id;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

My interface for the Api Call is as follows:

public interface UserEvents {

@GET("/user/get_events")
void getEvents(@Header("Authorization")String token_id,
@Query("event_type")String event_type,
@Query("postal_code")int postalCode,
@Query("per_page") int perPage ,
@Query("lat") int lat,
@Query("lon") int lon,
@Query("month")int month,
@Query("page")int page,
Callback<List<EventObject>>callback) ;

}

Here is its implementation in my code :

UserEvents mUserEvents = mRestAdapter.create(UserEvents.class);
mUserEvents.getEvents(token_Id, "sports",11209,25,0, 0, 9, 2, new Callback <List<EventObject>>() {
@Override
public void success(List<EventObject> eventObjects, retrofit.client.Response response) {
Log.d(TAG,"Success");
            }

There is alot going on here, but i believe that i am probably going wrong with how i am handling the JSON. When i copied and pasted in my JSON to the Pojo generator, i did not include "status:success, " data:{

I essentially just used the entire entry of an element in the Array ( everything from {sort_key onward until the next sort key ) and pushed that through the converter.

This is my first try at Retrofit and API work, and parsing anything this complicated. I am hoping its something that someone else will be able to point out. I have googled as well i could to sort this out with no luck.

Thanks for looking.

like image 331
WillParrish Avatar asked Aug 25 '14 21:08

WillParrish


1 Answers

The main problem is that you are not getting the root element of the response. You need to create an entity "response" that gets the items status and data. It would look something like this:

public class RootObject {

    @Expose
    private String status;
    @Expose
    private EventObject data;

    //getters and setters here
}

Then when you make the callback you should point to your RootObject, mUserEvents.getEvents(token_Id, "sports",11209,25,0, 0, 9, 2, new Callback <RootObject>()

One more thing, Retrofit uses GSON to parse your json reponse. It means that when you create the entities, the variables need to match the name of the objects coming in the response. If it doesn't you need to tell GSON how to map the variables, like this:

@SerializedName("extended_address")
@Expose
private String extendedAddress;

In that case the value coming in the json is "extended_address" and will be mapped to the String extendedAddress. If you don't put that @SerializedName line the parsing will fail. If you want to skip that line then you can call your variable "extended_address" so it matches the response.

The @Expose is needed by GSON to parse the variable below it. If a variable doesn't have it then GSON will ignore that parsing. So you need to fix both the @Expose and @SerializedName on your entities so GSON works correctly.

Hope it helps.

like image 66
Javier Mendonça Avatar answered Nov 04 '22 21:11

Javier Mendonça