【问题标题】:Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ JSON Array Kotlin预期为 BEGIN_ARRAY,但在第 1 行第 2 列路径为 BEGIN_OBJECT $ JSON Array Kotlin
【发布时间】:2021-09-23 19:14:56
【问题描述】:

我想检索一个 JSON 数组,我该如何调整我的代码库。我使用了改造库来检索数据,并使用了 MVVM 架构。我收到错误 Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $.

这是我的端点类:

 @GET("v2/venues/search")
    fun fetchAllVenues(): Call<List<Venue>>
    }

这是我的存储库类:

class VenueRepository {

    private var apiInterface: VenuesEndpoint? = null

    init {
        apiInterface = ApiClient.getApiClient().create(VenuesEndpoint::class.java)
    }

    fun fetchAllVenues(): MutableLiveData<List<Venue>?> {

        val data = MutableLiveData<List<Venue>?>()

        apiInterface?.fetchAllVenues()?.enqueue(object : Callback<List<Venue>> {

            override fun onFailure(call: Call<List<Venue>>, t: Throwable) {
                data.value = null
            }

            override fun onResponse(
                call: Call<List<Venue>>,
                response: Response<List<Venue>>
            ) {

                val res = response.body()
                if (response.code() == 200 && res != null) {
                    data.value = res
                } else {
                    data.value = null
                }

            }
        })

        return data

    }


}

这是我的模型类:

data class Venue(var id:Int,var name:String)

这是我的视图模型类:

class VenueViewModel : ViewModel() {
    private var venueRepository: VenueRepository? = null
    var postModelListLiveData: MutableLiveData<List<Venue>?>? = null


    init {
        venueRepository = VenueRepository()
        postModelListLiveData = MutableLiveData()
    }

    fun fetchAllVenues() {
        postModelListLiveData = venueRepository?.fetchAllVenues()

    }


}

这是我要检索的 JSON:

"response": { "venues": [ { "id": "4b83cb72f964a520d71031e3" "name": "Stadhuis" "contact": { "phone": "+3114010" "formattedPhone": "+31 14010" "twitter": "rotterdam" } "location": { "address": "Coolsingel 40" "lat": 51.92258962728412 "lng": 4.480227190204032 "labeledLatLngs": [ "0": { "label": "display" "lat": 51.92258962728412 "lng": 4.480227190204032 } ] "postalCode": "3011 AD" "cc": "NL" "city": "Rotterdam" "state": "Zuid-Holland" "country": "Nederland" "formattedAddress": [ "0": "Coolsingel 40" "1": "3011 AD Rotterdam" "2": "Nederland" 

【问题讨论】:

  • 你能分享一下json的样子吗?
  • "response": { "venues": [ { "id": "4b83cb72f964a520d71031e3" "name": "Stadhuis" "contact": { "phone": "+3114010" "formattedPhone": "+31 14010" "twitter": "鹿特丹" } "location": { "address": "Coolsingel 40" "lat": 51.92258962728412 "lng": 4.480227190204032 "labeledLatLngs": [ "0": { "label": "display" "lat": 51.92258962728412 "lng": 4.480227190204032 } ] "postalCode": "3011 AD" "cc": "NL" "city": "Rotterdam" "state": "Zuid-Holland" "country": “Nederland”“formattedAddress”:[“0”:“Coolsingel 40”“1”:“3011 AD Rotterdam”“2”:“Nederland”]}
  • 您可以更新您的问题并包含 json

标签: android arrays kotlin mvvm retrofit


【解决方案1】:

问题是,响应返回给你venues,而你期待的是List&lt;Venue&gt;,所以对你有用的是,创建另一个像这样的数据类:

data class Venues(
 val venues: List<Venue>
)

然后在GET请求里面返回Call&lt;Venues&gt; 一定要告诉你是否可以解决它:)

更新

好的,这有点冗长,但最后是您的详细解决方案,希望这可以为您解决所有问题!

视图模型

import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel

class ViewModel : ViewModel() {

    private val repository = Repository()

    fun getData(longLat: String, date: String): LiveData<mainResponse?> {

        repository.fetch(longLat, date)
        return repository.data
    }
}

存储库

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class Repository {

    private val _data: MutableLiveData<mainResponse?> = MutableLiveData(null)
    val data: LiveData<mainResponse?> get() = _data

    fun fetch(longlat: String, date: String) {

        val retrofit = Retro()
        val api = retrofit.retro.create(api::class.java)

        api.get(
            longLat = longlat,
            date = date
        ).enqueue(object : Callback<mainResponse>{

            override fun onResponse(call: Call<mainResponse>, response: Response<mainResponse>) {

                val res = response.body()
                if (response.code() == 200 && res != null) {

                    _data.value = res

                } else {

                    _data.value = null
                }
            }

            override fun onFailure(call: Call<mainResponse>, t: Throwable) {
                _data.value = null
            }
        })
    }
}

主活动

private val viewModel by viewModels<ViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    viewModel.getData(
        longLat = "40.7,-74", // sample latitude and longitude
        date = "20210715" // date format is: YYYYMMDD
    ).observe(this, Observer {

        it?.let { res ->

            res.response.venues.forEach { venue ->

                val name = venue.name
                val location = venue.location

                Log.d("name ",name)
                Log.d("address ", location.address)
            }
        }
    })
  }
}

API接口

import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query

interface api {

    @GET("v2/venues/search")
    fun get(
        @Query("ll") longLat: String,
        @Query("client_id") id: String = Const.clientId,
        @Query("client_secret") secret: String = Const.clientSecret,
        @Query("v") date: String
    ): Call<mainResponse>
}

模型类

主响应

数据类 mainResponse( val响应:响应 )

回应

data class Response(
val venues: List<Venue>,
val confident: Boolean
)

位置

data class Location(
val address: String,
val crossStreet: String,
val lng: Double,
val lat: Double
)

场地

data class Venue(
val id: String,
val name: String,
val location: Location
)

常量

object Const {

const val BASE_URL = "https://api.foursquare.com"
const val clientId = "" // add yours
const val clientSecret = "" // add yours
}

复古

class Retro {

val retro = Retrofit.Builder()
    .baseUrl(Const.BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .build()
}

依赖关系:确保添加activity-ktx以便在activity中使用ViewModel

def coroutines_version = "1.4.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutines_version"

def lifecycle_version = "2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"

def retrofit_version = "2.9.0"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"

implementation "androidx.activity:activity-ktx:1.2.3"

【讨论】:

  • 我应该如何调整存储库类?
  • data 更改为MutableLiveData&lt;Venues&gt;Call 也更改为Call&lt;Venues&gt;
  • 您也需要在ViewModel 中进行类似的更改,以及该函数在存储库中的返回类型
  • 我的 MainActivity 中有这段代码。场地ViewModel.postModelListLiveData?.observe(this, Observer { if (it!=null){ rv_home.visibility = View.VISIBLE adapter.setData(it as ArrayList) }else{ println("出了点问题") } progress_home .visibility = View.GONE }) 我该如何更改?
  • 所以当您调用adapter.setData(it) 时,基本上现在您需要将其更改为adapter.setData(it.venues) :)
猜你喜欢
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 2020-01-29
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 2020-01-06
  • 1970-01-01
相关资源
最近更新 更多