Android Json异常:应为BEGIN\u对象,但为BEGIN\u数组
我花了3个小时,找不到解析错误的原因 我有这个JSONAndroid 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.
[
{
"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>>
}