让 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 {
...
}
YellCategory
和 YelpLocation
也应该有注释。
在您的数据中添加 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 注释,因为不需要
我无法让 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 {
...
}
YellCategory
和 YelpLocation
也应该有注释。
在您的数据中添加 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 注释,因为不需要