Заставьте сериализатор Kotlin работать с Retrofit - PullRequest
1 голос
/ 19 марта 2020

Не могу заставить Kotlin Сериализатор работать с 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>
}

Активность

    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: Невозможно запустить действие ComponentInfo {com.xx.xx / com.xx.xx.MainActivity}: java. lang.IllegalArgumentException: Невозможно создать конвертер для класса com.xx.xx.YelpSearchResult

Невозможно создать конвертер для класса com.xx.xx.YelpSearchResult для метода YelpService.searchRestaurants

Причина: kotlinx.serialization.SerializationException: Невозможно найти сериализатор без аргументов для класса YelpSearchResult. Для универсальных классов, таких как списки, укажите сериализатор явно.

Что я делаю не так? спасибо за любые указания.

Ответы [ 3 ]

3 голосов
/ 24 марта 2020

Вы забыли поместить аннотацию @Serializable поверх YelpRestaurant

@Serializable
data class YelpRestaurant {
...
}

YellCategory и YelpLocation также должна иметь аннотацию на месте.

0 голосов
/ 30 марта 2020

добавьте эту зависимость в 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 потому что не нужно

0 голосов
/ 28 марта 2020

Добавить Сериализуемый в ваших классах данных

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
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...