SomeAndroidProgrammar
SomeAndroidProgrammar

Reputation: 41

GSON Expected BEGIN_ARRAY but was STRING at line 1 error

I am trying to parse a String array using Retrofit and GSON which is returned from the API:

This is what the response normally looks like (CASE 1):

["Scan finished, scan information embedded in this object", "https://www.virustotal.com/url/297c349554bdc7e2f09a85be309f08cb2f16a9174068bd5bc6e298ed90a5eed9/analysis/1485313628/", 8, 64]

This is what the response looks like in a specific case (CASE 2):

["Scan request successfully queued, come back later for the report", "https://www.virustotal.com/url/d06ed0b4b29aab735ee7b85c5c0af98fd4d983edcc597afe60e4c4ac2e25ea08/analysis/1485847248/", null, null]

In this case (CASE 2), I am getting an error from Retrofit/GSON:

W/System.err: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 2 path $
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:106)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at okhttp3.RealCall$AsyncCall.execute(RealCall.java:133)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
01-31 13:42:41.922 15746-15746/com.ssrij.testapp W/System.err:     at java.lang.Thread.run(Thread.java:761)

I call the API like this:

Call<ArrayList<String>> scanResults = myAPI.getScanResults(id);
scanResults.enqueue(...)

and the array gets populated fine in the normal case (CASE 1), but in this case (CASE 2), it throws the error.

I think it's because of the null values. I tried using a custom type adapter but it didn't fix the issue, also setting serializeNulls() on GsonBuilder didn't fix the issue.

Does anyone know a solution?

EDIT: After some more debugging, it seems like the server is returning a string in CASE 2 instead of the String array for some reason. When I visit the link manually, I do see the string array, but for some reason the response is String.

Upvotes: 3

Views: 2866

Answers (1)

dimo414
dimo414

Reputation: 48804

"Expected BEGIN_ARRAY but was STRING" means that the character Gson is parsing is a ", but it expected a [ (since you're trying to parse a list). Since the input doesn't correspond to the expected input, Gson has to fail. From Gson's perspective the case 2 input isn't any different than the case 1 input (and if nulls were an issue, the error message would say something to that effect).

Since this input isn't trusted (it's coming from a third-party server?) you should add some error handling code around the parse call, in order to account for the possibility that the input is malformed. At a minimum logging the received input upon failure would immediately make it clear that you're not receiving the expected array.

Upvotes: 2

Related Questions