改造 API 调用返回 null
Posted
技术标签:
【中文标题】改造 API 调用返回 null【英文标题】:Retrofit API call returns null 【发布时间】:2021-10-28 01:39:59 【问题描述】:这是我尝试使用的 API/JSON 数据:https://pogoapi.net/api/v1/pokemon_names.json
问题是当我尝试解析 JSON 响应时,只返回 null。
型号:
data class ListOfReleasedPokemon(
val releasedPokemon: List<PokemonResponse>
)
data class PokemonResponse(
val pokemonMap: Map<String, ReleasedPokemonModel>
)
data class ReleasedPokemonModel(
val id: Int,
val name: String
)
API 调用:
interface PogoApi
@GET("released_pokemon.json")
suspend fun getReleasedPokemon(): ListOfReleasedPokemon
应用模块:
@Module
@InstallIn(SingletonComponent::class)
object AppModule
@Singleton
@Provides
fun providePokemonRepository(
pogoApi: PogoApi
) = PokemonRepository(pogoApi)
@Singleton
@Provides
fun providePogoApi(): PogoApi
// val gson = GsonBuilder()
// .registerTypeAdapter(ReleasedPokemonModel::class.java, JsonDeserializer())
// .create()
return Retrofit.Builder()
.baseUrl(POGO_API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(PogoApi::class.java)
存储库(发现错误的位置):
@ActivityScoped
class PokemonRepository @Inject constructor(
private val pogoApi: PogoApi
)
suspend fun getReleasedPokemonList(): Resource<ListOfReleasedPokemon>
val response = try
pogoApi.getReleasedPokemon()
// Returns null
catch(e: IOException)
return Resource.Error("Please check your internet connection")
catch(e: HttpException)
return Resource.Error("Unexpected response")
Log.d("MainActivity", "GetPokemonReleasedList Run with no errors")
return Resource.Success(data = response)
任何帮助将不胜感激!
【问题讨论】:
我看到API中的列表项实际上不是列表,它是一个常规对象,里面包含其他对象。也许您应该查看您的数据响应。 如果它是这种格式,我有办法解析它吗? 【参考方案1】:哦,我现在才注意到您似乎有一个与此 Json 解析器相关的问题。
好吧,在此评论中,我将详细指导您的这个项目。 因为上一个问题您只问了如何使用未定义的键解析 Json。
首先,创建一个自定义的 Json Deserializer。因为这里你的数据 api 有一个未定义的键。在这里,我将使用自定义 Json Deserializer 创建 1 个 gson。如下:
口袋妖怪反应
data class PokemonResponse(
val pokemonMap: List<StringReleasedPokemonModel>
)
data class ReleasedPokemonModel(
val id: Int,
val name: String
)
GsonHelper.kt
object GsonHelper
fun create(): Gson = GsonBuilder().apply
registerTypeAdapter(PokemonResponse::class.java, PokemonType())
setLenient()
.create()
private class PokemonType : JsonDeserializer<PokemonResponse>
override fun deserialize(
json: JsonElement?,
typeOfT: Type?,
context: JsonDeserializationContext?
): PokemonResponse
val list = mutableListOf<ReleasedPokemonModel>()
// Get your all key
val keys = json?.asJsonObject?.keySet()
keys?.forEach key ->
// Get your item with key
val item = Gson().fromJson<ReleasedPokemonModel>(
json.asJsonObject[key],
object : TypeToken<ReleasedPokemonModel>() .type
)
list.add(item)
return PokemonResponse(list)
接下来,将这个 Gson 提供给你的 Dagger 或 Hilt。
AppModule.kt
@Module
@InstallIn(SingletonComponent::class)
object AppModule
@Provides
fun provideGson(): Gson = GsonHelper.create()
...
然后你修改你的addConverterFactory
如下:
AppModule.kt
@Module
@InstallIn(SingletonComponent::class)
object AppModule
@Provides
fun provideGson(): Gson = GsonHelper.create()
@Singleton
@Provides
fun providePogoApi(gson: Gson): PogoApi = Retrofit.Builder()
.baseUrl(POGO_API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(PogoApi::class.java)
在PogoApi
中,将getReleasedPokemon()
的返回类型改为PokemonResponse
。
interface PogoApi
@GET("released_pokemon.json")
suspend fun getReleasedPokemon(): PokemonResponse
最后,在您的存储库中,编辑以下内容:
PokemonRepository.kt
@ActivityScoped
class PokemonRepository @Inject constructor(
private val pogoApi: PogoApi
)
suspend fun getReleasedPokemonList(): Resource<PokemonResponse> = try
val response = pogoApi.getReleasedPokemon()
Log.d("MainActivity", "list: $response")
Resource.Success(data = response)
catch(e: IOException)
Resource.Error("Please check your internet connection")
catch(e: HttpException)
Resource.Error("Unexpected response")
【讨论】:
以上是关于改造 API 调用返回 null的主要内容,如果未能解决你的问题,请参考以下文章
改造 - 是不是可以避免从应用程序拦截器调用实际 api 并返回硬编码响应?