Sai Kiran Sai Kiran - 2 months ago 17
Android Question

Expected BEGIN_ARRAY but was STRING Retrofit Android

Json Data

[
{
"date": "25-09-2016",
"_id": {
"$oid": "57e601bbf2a9d92a445ef8a3"
},
"createdAt": "2016-09-24 10:01:55 +0530",
"horoscope": [
{
"date": "25-09-2016",
"sunsign": "aries",
"horoscope": "Testing.."
},
{
"date": "25-09-2016",
"sunsign": "taurus",
"horoscope": "Testing.."
},
{
"date": "25-09-2016",
"sunsign": "pisces",
"horoscope": "Testing.."
}
]
}
]


HoroscopeModel.java:

public class HoroscopeModel {

private Date date;
private Date createdAt;
private List<HoroscopeModel> horoscope;

public List<HoroscopeModel> getHoroscope() {
return horoscope;
}

public void setHoroscope(List<HoroscopeModel> horoscope) {
this.horoscope = horoscope;
}


public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}

public Date getCreatedAt() {
return createdAt;
}

public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}

public List<HoroscopeModel> getHoroscopeList() {
return horoscope;
}

public void setHoroscopeList(List<HoroscopeModel> horoscopeList) {
this.horoscope = horoscopeList;
}
}


Horoscope.java

public class Horoscope {

Date date;
String sunshine;
String horoscope;

public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}

public String getSunShine() {
return sunshine;
}

public void setSunShine(String sunShine) {
this.sunshine = sunShine;
}

public String getHoroscope() {
return horoscope;
}

public void setHoroscope(String horoscope) {
horoscope = horoscope;
}
}


ApiInterface.java

public interface ApiInterface {

@GET("/get_horoscope")
Call<List<HoroscopeModel>> getHoroscope();
}


Retrofit:

private void setupRestClient() {
OkHttpClient.Builder client = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
client.addInterceptor(loggingInterceptor);


Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create(getGson()))
.build();

REST_CLIENT = retrofit.create(ApiInterface.class);
}

private Gson getGson() {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new DateDeserializer());
builder.setPrettyPrinting();
return builder.create();
}


DateDeserializer.java

public class DateDeserializer implements JsonDeserializer<Date> {
private static final String TAG = "DateDeserializer";
private static final String[] DATE_FORMATS = new String[]{
"yyy-MM-dd hh:mm:ss Z",//2016-09-24 08:18:56 +0530
"dd-MM-yyyy"
};

@Override
public Date deserialize(JsonElement jsonElement, Type typeOF,
JsonDeserializationContext context) throws JsonParseException {
for (String format : DATE_FORMATS) {
try {
return new SimpleDateFormat(format, Locale.US).parse(jsonElement.getAsString());
} catch (ParseException e) {
}
}
throw new JsonParseException("Unparseable date: \"" + jsonElement.getAsString()
+ "\". Supported formats: " + Arrays.toString(DATE_FORMATS));
}
}


With everything perfectly set up it throws an error saying
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 183 path $[0].horoscope[0].horoscope
, Please let me know is there any mistake in my code. Thanks in advance.

Answer

The error message is quite self-explanatory.

$[0].horoscope[0].horoscope is a String, but you're trying to deserialize it into a List.

That's because in HoroscopeModel you're defining horoscope as type of List<HoroscopeModel>, instead of List<Horoscope>.

Gson is trying to deserialize the value of horoscope (a String) into the horoscope field of HoroscopeModel (a List) instead of the horoscope field of Horoscope (a String).

In HoroscopeModel, change to following field:

private List<HoroscopeModel> horoscope;

To this:

private List<Horoscope> horoscope;

(and don't forget to modify the corresponding methods also)