预期 BEGIN_ARRAY 但在第 1 行第 2 列路径 BEGIN_OBJECT $ JSON Array Kotlin

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ JSON Array Kotlin

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

这是我的终点class:

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

这是我的存储库class:

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

    }


}

这是我的模型class:

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

这是我的视图模型class:

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" 

问题是,响应 return 是你 venues 并且你期待 List<Venue>,所以对你有用的是,创建另一个数据 class就像这样:

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

然后在GET请求里面returnCall<Venues> 请告诉我这是否为您解决了 :)

更新

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

ViewModel

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
    }
}

Repository

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
            }
        })
    }
}

MainActivity

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 Interface

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>
}

Model Classes

mainResponse

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

Response

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

Location

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

Venue

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

Const

object Const {

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

Retro

class Retro {

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

Dependencies: make sure to add activity-ktx for using ViewModel in activity

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"