Android Json异常:应为BEGIN\u对象,但为BEGIN\u数组

Android Json异常:应为BEGIN\u对象,但为BEGIN\u数组,android,kotlin,gson,retrofit,kotlin-coroutines,Android,Kotlin,Gson,Retrofit,Kotlin Coroutines,我花了3个小时,找不到解析错误的原因 我有这个JSON [ { "id": "WMWSW31030T222518", "modelName": "MINI", "name": "Vanessa", "make": "BMW", "latitude": 48.134557, "longitude": 11.576921, "carImageUrl": "https://cdn.sixt.io/codingtask/images/mini.

我花了3个小时,找不到解析错误的原因

我有这个JSON

[
  {
    "id": "WMWSW31030T222518",
    "modelName": "MINI",
    "name": "Vanessa",
    "make": "BMW",
    "latitude": 48.134557,
    "longitude": 11.576921,
    "carImageUrl": "https://cdn.sixt.io/codingtask/images/mini.png"
  },
  {
    "id": "WMWSU31070T077232",
    "modelName": "MINI",
    "name": "Regine",
    "make": "BMW",
    "latitude": 48.114988,
    "longitude": 11.598359,
    "carImageUrl": "https://cdn.sixt.io/codingtask/images/mini.png"
  }
]
解析后,我得到了这个错误

An error happened: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2
这是我的密码

--存储库--

interface CarRepository{
suspend fun getCars():LiveData
}
类CarRepositoryImpl(私有val数据源:CarDatasource,
私人val dao:卡道(CarDao):CarRepository{
重写suspend fun getCars():LiveData{
返回对象:NetworkBoundResource(){
覆盖有趣的processResponse(响应:ApiResult):列表
=response.items
覆盖suspend fun saveCallResults(项目:列表)
=dao.save(项目)
重写fun shouldFetch(数据:列表?):布尔值
=data==null | | data.isEmpty()
覆盖suspend fun loadFromDb():列表
=dao.getCars()
重写createCallAsync():延迟
=datasource.fetchCars()
}.build().asLiveData()
}
}
--汽车服务--

接口服务{
@获取(“汽车”)
fun fetchCars():延迟
}
--芹菜--

数据类ApiResult(val项:列表)
--网络边界资源--

抽象类NetworkBoundResource{
private val result=MutableLiveData()
private val supervisorJob=supervisorJob()
suspend fun build():NetworkBoundResource{
withContext(Dispatchers.Main){result.value=
正在加载资源(null)
}
CoroutineScope(coroutineContext).启动(supervisorJob){
val dbResult=loadFromDb()
if(shouldFetch(dbResult)){
试一试{
fetchFromNetwork(dbResult)
}捕获(e:例外){
Log.e(“NetworkBoundResource”,“发生错误:$e”)
setValue(Resource.error(e,loadFromDb()))
}
}否则{
Log.d(NetworkBoundResource::class.java.name,“从本地数据库返回数据”)
setValue(Resource.success(dbResult))
}
}
还这个
}
fun asLiveData()=结果为LiveData
// ---
从网络获取的私有挂起数据(dbResult:ResultType){
Log.d(NetworkBoundResource::class.java.name,“从网络获取数据”)
setValue(Resource.loading(dbResult))//快速分派最新值(UX用途)
val apiResponse=createCallAsync().await()
Log.e(NetworkBoundResource::class.java.name,“从网络获取的数据”)
saveCallResults(processResponse(apiResponse))
setValue(Resource.success(loadFromDb()))
}
@主线
private-fun-setValue(newValue:Resource){
Log.d(NetworkBoundResource::class.java.name,“资源:”+newValue)
if(result.value!=newValue)result.postValue(newValue)
}
@工作线程
受保护的抽象fun processResponse(响应:RequestType):ResultType
@工作线程
受保护的抽象suspend fun saveCallResults(项:ResultType)
@主线
受保护的抽象fun shouldFetch(数据:ResultType?):布尔值
@主线
受保护的抽象挂起fun loadFromDb():ResultType
@主线
受保护的抽象对象createCallAsync():延迟
--资源--

数据类资源(val状态:状态,val数据:T?,val错误:可丢弃?){
伴星{
有趣的成功(数据:T?):资源{
返回资源(
地位,成功,
数据,
无效的
)
}
有趣的错误(错误:可丢弃,数据:T?):资源{
返回资源(
状态错误,
数据,
错误
)
}
乐趣加载(数据:T?):资源{
返回资源(
状态。加载,
数据,
无效的
)
}
}
枚举类状态{
成功,,
错误,
加载
}
}

有谁能告诉我解析器失败的原因是什么吗?

错误在于您应该使用列表而不是ApiResult,因为ApiResult是一个带有列表的对象,而GSON尝试解析一个对象并查找带有atribute名称项的列表

//change to List<Car>
interface CarService {

    @GET("cars")
    fun fetchCars(): Deferred<List<Car>>
}
//更改为列表
接口服务{
@获取(“汽车”)
fun fetchCars():延迟
}

这里的错误是,您应该使用列表而不是ApiResult,因为ApiResult是一个具有列表的对象,而GSON尝试解析一个对象并查找具有atribute名称项的列表

//change to List<Car>
interface CarService {

    @GET("cars")
    fun fetchCars(): Deferred<List<Car>>
}
//更改为列表
接口服务{
@获取(“汽车”)
fun fetchCars():延迟
}
data class ApiResult<T>(val items: List<T>)
abstract class NetworkBoundResource<ResultType, RequestType> {

    private val result = MutableLiveData<Resource<ResultType>>()
    private val supervisorJob = SupervisorJob()

    suspend fun build(): NetworkBoundResource<ResultType, RequestType> {
        withContext(Dispatchers.Main) { result.value =
            Resource.loading(null)
        }
        CoroutineScope(coroutineContext).launch(supervisorJob) {
            val dbResult = loadFromDb()
            if (shouldFetch(dbResult)) {
                try {
                    fetchFromNetwork(dbResult)
                } catch (e: Exception) {
                    Log.e("NetworkBoundResource", "An error happened: $e")
                    setValue(Resource.error(e, loadFromDb()))
                }
            } else {
                Log.d(NetworkBoundResource::class.java.name, "Return data from local database")
                setValue(Resource.success(dbResult))
            }
        }
        return this
    }

    fun asLiveData() = result as LiveData<Resource<ResultType>>

    // ---

    private suspend fun fetchFromNetwork(dbResult: ResultType) {
        Log.d(NetworkBoundResource::class.java.name, "Fetch data from network")
        setValue(Resource.loading(dbResult)) // Dispatch latest value quickly (UX purpose)
        val apiResponse = createCallAsync().await()
        Log.e(NetworkBoundResource::class.java.name, "Data fetched from network")
        saveCallResults(processResponse(apiResponse))
        setValue(Resource.success(loadFromDb()))
    }

    @MainThread
    private fun setValue(newValue: Resource<ResultType>) {
        Log.d(NetworkBoundResource::class.java.name, "Resource: "+newValue)
        if (result.value != newValue) result.postValue(newValue)
    }

    @WorkerThread
    protected abstract fun processResponse(response: RequestType): ResultType

    @WorkerThread
    protected abstract suspend fun saveCallResults(items: ResultType)

    @MainThread
    protected abstract fun shouldFetch(data: ResultType?): Boolean

    @MainThread
    protected abstract suspend fun loadFromDb(): ResultType

    @MainThread
    protected abstract fun createCallAsync(): Deferred<RequestType>
data class Resource<out T>(val status: Status, val data: T?, val error: Throwable?) {
    companion object {
        fun <T> success(data: T?): Resource<T> {
            return Resource(
                Status.SUCCESS,
                data,
                null
            )
        }

        fun <T> error(error: Throwable, data: T?): Resource<T> {
            return Resource(
                Status.ERROR,
                data,
                error
            )
        }

        fun <T> loading(data: T?): Resource<T> {
            return Resource(
                Status.LOADING,
                data,
                null
            )
        }
    }

    enum class Status {
        SUCCESS,
        ERROR,
        LOADING
    }
}
//change to List<Car>
interface CarService {

    @GET("cars")
    fun fetchCars(): Deferred<List<Car>>
}