这是我尝试调用以下接口的方法时遇到的错误:
interface TvShowService {
@GET("tv/{tv_id}")
suspend fun getDetails(
@Path("tv_id") id: Int,
@QueryMap queries: Map<String, String>
): 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,
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 {
""
}
}
}
网络模块.kt
@Singleton
@Provides
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit =
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
我检查了依赖项,它们是最新的,我还有一个方法可以执行相同的操作,但对于电影来说并且它有效,因此它成功填充了
MovieDetailsDTO
。
可能存在的问题或至少可能的解决方案是什么。环顾四周,我发现的解决方案大多涉及重复属性之间的名称。
有两个错误实际上涉及相同的父类和子类属性,但一开始我无法拦截它们。
让我们检查一下继承自
TvShowDetailsDTO
的两个类 TvShowDTO
:
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
//...
)
通过将父类的此属性设置为私有,它在子类中不可见(TvShowDetailsDTO),因此定义了两次,显然无法映射,导致映射器中出现错误。
解决方案是使父类属性仅在层次结构级别可见(protected),并在子类中删除重复属性前面的val关键字,如下所示:
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,
另一个非常相似的问题存在于
List<CreatedByDTO>
的 TvShowDetailsDTO
属性中,这里是类:
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?,
始终是在父类中创建私有属性的类层次结构会导致相同的错误,在这种情况下,该属性被定义两次gender,解决方案始终相同,在父类中将其设为protected,这样从子类中删除关键字和 @SerializedName。
当我尝试添加第二组触及我的
provideRetrofit()
版本的调用时,我在 Android 应用程序中遇到了同样的错误。原始呼叫者需要 ScalarsConverterFactory
,新呼叫者需要 GsonConverterFactory
。我通过检查请求 URL 中是否存在仅出现在标量请求中的特定关键字来解决此问题,以相应地翻转转换器工厂。这不是一个出色的解决方案,但希望这可以帮助其他人,如果他们对转换器工厂有同样的问题。