JsonArray 到 Kotlin 数据 class 使用 Retrofit 和 GsonConverterFactory(预期 BEGIN_OBJECT 但为 BEGIN_ARRAY)
JsonArray to Kotlin data class using Retrofit and GsonConverterFactory(Expected BEGIN_OBJECT but was BEGIN_ARRAY)
我正在尝试从 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) 加载 quotesJson 文件。非常抱歉,如果这是愚蠢的或真的很容易。我还在为此苦苦挣扎。如果我能得到一个简短的解释为什么它是以其他方式完成的,我将不胜感激!
我查看了 Retrofit 的文档,搜索了所有类似的溢出问题。问题是,如果我尝试改变
fun getQuotes(): Deferred<Response<QuoteResponse>>
到
fun getQuotes(): Deferred<ResponseList<Quotes>>
我得到一个错误
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)
}
型号
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)```
您遇到的问题是因为响应是一个数组,但您正试图将其作为一个对象来处理。
这就是您的 QuoteApi 的样子
interface QuoteApi{
@GET("quotes.json")
fun getQuotes(): Deferred<Response<List<Quote>>>
}
说明:
为您更好地解释一下 - 您当前的预期反应是
data class QuoteResponse(
val results : List<Quote>
)
并且 Retrofit 和 Gson 期望您的 JSON 响应看起来像
{
"results": [...here would be your Qoute objects...]
}
实际上响应只是一个数组
[...here are Quote objects...]
.
我正在尝试从 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) 加载 quotesJson 文件。非常抱歉,如果这是愚蠢的或真的很容易。我还在为此苦苦挣扎。如果我能得到一个简短的解释为什么它是以其他方式完成的,我将不胜感激!
我查看了 Retrofit 的文档,搜索了所有类似的溢出问题。问题是,如果我尝试改变
fun getQuotes(): Deferred<Response<QuoteResponse>>
到
fun getQuotes(): Deferred<ResponseList<Quotes>>
我得到一个错误
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)
}
型号
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)```
您遇到的问题是因为响应是一个数组,但您正试图将其作为一个对象来处理。
这就是您的 QuoteApi 的样子
interface QuoteApi{
@GET("quotes.json")
fun getQuotes(): Deferred<Response<List<Quote>>>
}
说明: 为您更好地解释一下 - 您当前的预期反应是
data class QuoteResponse(
val results : List<Quote>
)
并且 Retrofit 和 Gson 期望您的 JSON 响应看起来像
{
"results": [...here would be your Qoute objects...]
}
实际上响应只是一个数组
[...here are Quote objects...]
.