Reputation: 117
I'm trying to load quotesJson file from github(https://github.com/JamesFT/Database-Quotes-JSON/blob/master/quotes.json). I'm new to retrofit and all of this, so I just tried following and understanding a tutorial(https://android.jlelse.eu/android-networking-in-2019-retrofit-with-kotlins-coroutines-aefe82c4d777) . Incredibly sorry if this is stupid or really easy. I'm still struggling with this. If i can get a short explanation of why it's done some other way I'd appreciate it!
I've looked at documentation for Retrofit, searched all of the similar overflow questions. The problem is, if I try to change
fun getQuotes(): Deferred<Response<QuoteResponse>>
to
fun getQuotes(): Deferred<ResponseList<Quotes>>
I get an error in
val quoteResponse = safeApiCall(...
private val okHttpClient = OkHttpClient().newBuilder()
.build()
fun retrofit() : Retrofit = Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://raw.githubusercontent.com/JamesFT/Database-Quotes-JSON/master/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
val quoteApi : QuoteApi = retrofit().create(QuoteApi::class.java)
}
model
val quoteAuthor : String,
val quoteText : String
)
// Data Model for the Response returned from the Api
data class QuoteResponse(
val results : List<Quote>
)
//A retrofit Network Interface for the Api
interface QuoteApi{
@GET("quotes.json")
fun getQuotes(): Deferred<Response<QuoteResponse>>
// fun getQuotes(): Deferred<Response<QuoteResponse>>
}
val quoteResponse = safeApiCall(
call = {api.getQuotes().await()}, // i get the error here if i change something myself
errorMessage = "Error Fetching Popular Movies"
)
return quoteResponse?.results?.toMutableList()
}
suspend fun <T : Any> safeApiCall(call: suspend () -> Response<T>, errorMessage: String): T? {
val result : Result<T> = safeApiResult(call,errorMessage)
var data : T? = null
when(result) {
is Result.Success ->
data = result.data
is Result.Error -> {
Log.d("1.DataRepository", "$errorMessage & Exception - ${result.exception}")
}
}
return data
}
Process: com.example.quoteappmvvm, PID: 7373
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
...
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:215)```
Upvotes: 1
Views: 4449
Reputation: 690
The problem you are facing is because the response is an array but you are trying to handle it as an object.
This is how your QuoteApi should look like
interface QuoteApi{
@GET("quotes.json")
fun getQuotes(): Deferred<Response<List<Quote>>>
}
Explanation: To explain it a little better for you - your current expected response is
data class QuoteResponse(
val results : List<Quote>
)
and Retrofit and Gson expect that your JSON response looks like
{
"results": [...here would be your Qoute objects...]
}
when actually the response is only an array
[...here are Quote objects...]
.
Upvotes: 6