I'm facing this issue on my project. I receive from api call a response like:
{
"aResponse": {
"listOfSomething": [
//here some data
]
}
}
And relative data classes are
data class ResponseClass(
val aResponse : AResponse
)
data class AResponse(
val listOfSomething : List<String>
)
Not it happen that when "listOfSomething" is empty, i receive this response:
{
"aResponse": {
"listOfSomething": ""
}
}
that throws (of course) the exception
com.squareup.moshi.JsonDataException: Expected BEGIN_OBJECT but was STRING
How can i solve it?
You are getting this error as when there is data you get array and when no data get string which is wrong in retrofit.
If there are no data insise listOfSomething then ask backend to send empty array instead of string.
{
"aResponse": {
"listOfSomething": []
}
}
instead of
{
"aResponse": {
"listOfSomething": ""
}
}
If your json result is gonna change depends of the result, first of all your backend is doing a bad job, then you have to "hack" a little bit your app to adapt the code...
Your POJO class should be :
data class MyResponse(
val aResponse: AResponse
)
data class AResponse(
val listOfSomething: Any
)
You can declare it as Any
which is not a good practise, but it's a workaround to make it work according to your backend. Is like in Java adding Object
Then you can do something in your onResponse
@Override
fun onResponse(response: Response<MyResponse>) {
if (response.isSuccess()) {
if (response.listOfSomething is String) {
//do something with the String
} else {
//do something with the List
}
}
}
First, your backend implementation is wrong. You should not send an empty string to represent an empty array.
If you can't fix it on backend side because the API are not under your control, you can try with something like this:
public final class IgnoreStringForArrays implements JsonAdapter.Factory {
@Retention(RetentionPolicy.RUNTIME)
@JsonQualifier
public @interface IgnoreJsonArrayError {
}
@Override
public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
if (annotations != null && annotations.size() > 0) {
for (Annotation annotation : annotations) {
if (annotation instanceof IgnoreJsonArrayError) {
final JsonAdapter<Object> delegate = moshi.nextAdapter(this, type, Types.nextAnnotations(annotations, IgnoreJsonArrayError.class));
return new JsonAdapter<Object>() {
@Override
public Object fromJson(JsonReader reader) throws IOException {
JsonReader.Token peek = reader.peek();
if (peek != JsonReader.Token.BEGIN_ARRAY) {
reader.skipValue();
return null;
}
return delegate.fromJson(reader);
}
@Override
public void toJson(JsonWriter writer, Object value) throws IOException {
delegate.toJson(writer, value);
}
};
}
}
}
return null;
}
}
like suggested here: https://github.com/square/moshi/issues/295#issuecomment-299636385
And then annotate your listOfSomething
with: IgnoreJsonArrayError
annotation
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.