Json 异常:预期 BEGIN_OBJECT 但 BEGIN_ARRAY
Json exception: Expected BEGIN_OBJECT but was BEGIN_ARRAY
我花了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<Resource<List<Car>>>
}
class CarRepositoryImpl(private val datasource: CarDatasource,
private val dao: CarDao): CarRepository{
override suspend fun getCars(): LiveData<Resource<List<Car>>> {
return object : NetworkBoundResource<List<Car>, ApiResult<Car>>() {
override fun processResponse(response: ApiResult<Car>): List<Car>
= response.items
override suspend fun saveCallResults(items: List<Car>)
= dao.save(items)
override fun shouldFetch(data: List<Car>?): Boolean
= data == null || data.isEmpty()
override suspend fun loadFromDb(): List<Car>
= dao.getCars()
override fun createCallAsync(): Deferred<ApiResult<Car>>
= datasource.fetchCars()
}.build().asLiveData()
}
}
--汽车服务--
interface CarService {
@GET("cars")
fun fetchCars(): Deferred<ApiResult<Car>>
}
--ApiResult--
data class ApiResult<T>(val items: List<T>)
--NetworkBoundResource--
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
}
}
谁能告诉我解析器失败的原因是什么?
错误在这里你应该使用列表而不是 ApiResult 因为 ApiResult 是一个带有列表的对象,而 GSON 试图解析一个对象并找到一个带有属性名称项的列表。
//change to List<Car>
interface CarService {
@GET("cars")
fun fetchCars(): Deferred<List<Car>>
}
我花了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<Resource<List<Car>>>
}
class CarRepositoryImpl(private val datasource: CarDatasource,
private val dao: CarDao): CarRepository{
override suspend fun getCars(): LiveData<Resource<List<Car>>> {
return object : NetworkBoundResource<List<Car>, ApiResult<Car>>() {
override fun processResponse(response: ApiResult<Car>): List<Car>
= response.items
override suspend fun saveCallResults(items: List<Car>)
= dao.save(items)
override fun shouldFetch(data: List<Car>?): Boolean
= data == null || data.isEmpty()
override suspend fun loadFromDb(): List<Car>
= dao.getCars()
override fun createCallAsync(): Deferred<ApiResult<Car>>
= datasource.fetchCars()
}.build().asLiveData()
}
}
--汽车服务--
interface CarService {
@GET("cars")
fun fetchCars(): Deferred<ApiResult<Car>>
}
--ApiResult--
data class ApiResult<T>(val items: List<T>)
--NetworkBoundResource--
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
}
}
谁能告诉我解析器失败的原因是什么?
错误在这里你应该使用列表而不是 ApiResult 因为 ApiResult 是一个带有列表的对象,而 GSON 试图解析一个对象并找到一个带有属性名称项的列表。
//change to List<Car>
interface CarService {
@GET("cars")
fun fetchCars(): Deferred<List<Car>>
}