让 Kotlin Serializer 与 Retrofit 一起工作

Make Kotlin Serializer work with Retrofit

我无法让 Kotlin Serializer 与 Retrofit 一起工作。我正在使用 com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.5.0 包和 Retrofit。

数据类

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable


@Serializable
data class YelpSearchResult(
    @SerialName("total") val total: Int,
    @SerialName("businesses") val restaurants: List<YelpRestaurant>
)

data class YelpRestaurant(
    val name: String,
    val rating: Double,
    val price: String,
    @SerialName("review_count") val numReviews: Int,
    @SerialName("distance") val distanceInMeters: Double,
    @SerialName("image_url") val imageUrl: String,
    val categories: List<YelpCategory>,
    val location: YelpLocation
) {

    fun displayDistance(): String {
        val milesPerMeter = 0.000621371
        val distanceInMiles = "%.2f".format(distanceInMeters * milesPerMeter)
        return "$distanceInMiles mi"
    }
}

data class YelpCategory(
    val title: String
)

data class YelpLocation(
    @SerialName("address1") val address: String
)

服务接口

public interface YelpService {
    @GET("businesses/search")
    fun searchRestaurants(
        @Header("Authorization") authHeader: String,
        @Query("term") searchTerm: String,
        @Query("location") location: String): Call<YelpSearchResult>
}

Activity

    val contentType = MediaType.get("application/json")
    val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(Json.asConverterFactory(contentType))
            .build()

    val yelpService = retrofit.create(YelpService::class.java)


    yelpService.searchRestaurants("Bearer ${api_key}",
        "Something", "Some Location").enqueue(
            object: Callback<YelpSearchResult> {
                override fun onFailure(call: Call<YelpSearchResult>, t: Throwable) {
                    Log.d("MainActivity", "err ${t}")

                }
                override fun onResponse(call: Call<YelpSearchResult>, response: Response<YelpSearchResult>) {
                    Log.d("MainActivity", "succ ${response}")
                }
            }
    )

当运行时,抛出的异常是,

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xx.xx/com.xx.xx.MainActivity}: java.lang.IllegalArgumentException: Unable to create converter for class com.xx.xx.YelpSearchResult

Unable to create converter for class com.xx.xx.YelpSearchResult for method YelpService.searchRestaurants

Caused by: kotlinx.serialization.SerializationException: Can't locate argument-less serializer for class YelpSearchResult. For generic classes, such as lists, please provide serializer explicitly.

我做错了什么?感谢任何指示。

您忘记将 @Serializable 注释放在 YelpRestaurant

之上
@Serializable
data class YelpRestaurant {
...
}

YellCategoryYelpLocation 也应该有注释。

在您的数据中添加 Serializable 类

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable


@Serializable
data class YelpSearchResult(
    @SerialName("total") val total: Int,
    @SerialName("businesses") val restaurants: List<YelpRestaurant>
)

@Serializable
data class YelpRestaurant(
    val name: String,
    val rating: Double,
    val price: String,
    @SerialName("review_count") val numReviews: Int,
    @SerialName("distance") val distanceInMeters: Double,
    @SerialName("image_url") val imageUrl: String,
    val categories: List<YelpCategory>,
    val location: YelpLocation
) {

    fun displayDistance(): String {
        val milesPerMeter = 0.000621371
        val distanceInMiles = "%.2f".format(distanceInMeters * milesPerMeter)
        return "$distanceInMiles mi"
    }
}

@Serializable
data class YelpCategory(
    val title: String
)

@Serializable
data class YelpLocation(
    @SerialName("address1") val address: String
)

将此依赖项添加到 yr gradle:

implementation 'com.squareup.retrofit2:converter-gson:2.6.2'

像这样更新您的改造构建器以使用 GsonConverterFactory:

 val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
              .addConverterFactory(GsonConverterFactory.create(Gson()))
            .build()

并删除 @Serializable 注释,因为不需要