gson 无法为类创建转换器,改进

yftpprvb  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(160)

  • 我使用图像是因为堆栈溢出中的代码格式给我带来了很多问题 *
    这是我在尝试调用以下接口的方法时遇到的错误:
interface TvShowService {

    @GET("tv/{tv_id}")
    suspend fun getDetails(
        @Path("tv_id") id: Int,
        @QueryMap queries: Map<String, String>
    ): TvShowDetailsDTO
}

在许多回答一个问题的EQUAL矿它建议检查,在类中被Map有相等的属性,但你可以看到没有:

class TvShowDetailsDTO(
    backdropPath: String,
    @SerializedName("created_by")
    val createdBy: List<CreatedByDTO>,
    @SerializedName("episode_run_time")
    private val episodeRunTime: List<Int>,
    @SerializedName("first_air_date")
    val firstAirDate: String,
    genres: List<GenreDTO>,
    val homepage: String,
    id: Int,
    @SerializedName("in_production")
    val inProduction: Boolean,
    val languages: List<String>,
    @SerializedName("last_air_date")
    val lastAirDate: String,
    @SerializedName("last_episode_to_air")
    val lastEpisodeToAir: EpisodeDTO,
    name: String,
    val networks: List<NetworkDTO>,
    @SerializedName("next_episode_to_air")
    val nextEpisodeToAir: EpisodeDTO?,
    @SerializedName("number_of_episodes")
    val numberOfEpisodes: Int,
    @SerializedName("number_of_seasons")
    val numberOfSeasons: Int,
    originCountry: List<String>,
    originalLanguage: String,
    originalName: String,
    overview: String,
    popularity: Double,
    posterPath: String,
    @SerializedName("production_companies")
    val productionCompanies: List<ProductionCompanyDTO>,
    @SerializedName("production_countries")
    val productionCountries: List<ProductionCountryDTO>,
    val seasons: List<SeasonDTO>,
    @SerializedName("spoken_languages")
    val spokenLanguages: List<SpokenLanguageDTO>,
    val status: String,
    val tagline: String,
    val type: String,
    voteAverage: Double,
    voteCount: Int
) : TvShowDTO(
    backdropPath,
    firstAirDate,
    genres,
    id,
    name,
    originCountry,
    originalLanguage,
    originalName,
    overview,
    popularity,
    posterPath,
    voteAverage,
    voteCount
) {
    private fun formatTimeMeasurement(timeMeasurement: Int): String {
        val hours = timeMeasurement / 60
        val minutes = timeMeasurement % 60
        return String.format("%02d h %02d min", hours, minutes)
    }

    val formattedEpisodesRuntime: List<String>
        get() {
            return episodeRunTime.map { formatTimeMeasurement(it) }
        }

}

open class TvShowDTO(
    @SerializedName("backdrop_path")
    val backdropPath: String?,
    @SerializedName("first_air_date")
    private val firstAirDate: String,
    @SerialName("genre_ids")
    val genres: List<GenreDTO>,
    val id: Int,
    val name: String,
    @SerializedName("origin_country")
    val originCountry: List<String>,
    @SerializedName("original_language")
    val originalLanguage: String,
    @SerializedName("original_name")
    val originalName: String,
    val overview: String,
    val popularity: Double,
    @SerializedName("poster_path")
    val posterPath: String?,
    @SerializedName("vote_average")
    val voteAverage: Double,
    @SerializedName("vote_count")
    val voteCount: Int
) {
    private fun formatDate(date: String): String {
        val inputFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
        val outputFormat = SimpleDateFormat.getDateInstance()
        val formattedDate = inputFormat.parse(date)
        return outputFormat.format(formattedDate)
    }

    val formattedFirstAirDate: String
        get() {
            return if (firstAirDate.isNotEmpty()) {
                formatDate(firstAirDate)
            } else {
                ""
            }
        }
}

NetworkModule。kt

@Singleton
@Provides
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit =
    Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build()

我检查了依赖项,它们是最新的,我也有一个方法,执行相同的操作,但电影和它的工作,所以它成功地填充MovieDetailsDTO
可能的问题或至少可能的解决方案。环顾四周,我发现大多数解决方案涉及重复属性之间的名称。

bkhjykvo

bkhjykvo1#

解决方案

1°问题

有两个错误实际上涉及相同的父类和子类属性,但起初我无法拦截它们。
让我们看看继承自TvShowDTO的两个类TvShowDetailsDTO

class TvShowDetailsDTO(
     backdropPath: String?,
     @SerializedName("created_by")
     val createdBy: List<CreatedByDTO>,
     @SerializedName("episode_run_time")
     private val episodeRunTime: List<Int>,
     @SerializedName("first_air_date")
     val firstAirDate: String, <-- ERROR
     genres: List<GenreDTO>,
   //...
   ):TvShowDTO(
     backdropPath,
     firstAirDate,
     / /...
   )

他的班级爸爸:

open class TvShowDTO(
    @SerializedName("backdrop_path")
    val backdropPath: String?,
    @SerializedName("first_air_date")
    private val firstAirDate: String,<-- THE REAL ONE
    //...
    )

通过将父类的此属性设置为private,这在子类(TvShowDetailsDTO)中不可见,因此定义了两次,显然无法Map,导致Map器中出现错误。

1°解决方案

解决方案是使父类属性仅在层次结构级别(protected)可见,并在子类中删除重复属性前面的瓦尔关键字,如下所示:

open class TvShowDTO(
@SerializedName("backdrop_path")
val backdropPath: String?,
@SerializedName("first_air_date")
protected val firstAirDate: String,

class TvShowDetailsDTO(
backdropPath: String?,
@SerializedName("created_by")
val createdBy: List<CreatedByDTO>,
@SerializedName("episode_run_time")
private val episodeRunTime: List<Int>,
firstAirDate: String,

2°问题

另一个非常类似的问题存在于TvShowDetailsDTOList<CreatedByDTO>属性中,下面是类:

class CreatedByDTO(
    @SerializedName("credit_id")
    val creditId: String,
    val gender: Int?,
    id: Int,
    name: String,
    profilePath: String?
) : PersonDTO(
    id, name, profilePath, gender
)

open class PersonDTO(
val adult: Boolean,
@SerializedName("also_known_as")
val alsoKnownAs: List<String>,
val biography: String,
private val birthday: String?,
@SerializedName("deathday")
private val deathDay: String?,
private val gender: Int?,

总是一个类层次结构,在父类中创建属性,private会导致相同的错误,在这种情况下,属性被gender定义了两次,解决方案总是相同的,在父类中将其 protected,以便从子类中删除关键字和**@SerializedName**。

相关问题