android - 改造 API 调用返回 null
问题描述
这是我尝试使用的 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
)
接口调用:
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)
}
}
任何帮助将不胜感激!
解决方案
哦,我现在才注意到您似乎有一个与此 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。
应用模块.kt
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
fun provideGson(): Gson = GsonHelper.create()
...
}
然后你修改你addConverterFactory
的如下:
应用模块.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")
}
}
推荐阅读
- go - 测试时“无法在 Go Routine 中启动 NATS 服务器”
- android - 如何在没有 WorkContinuation 的情况下将顺序工作排入队列
- angular - Angular 依赖提供者没有提供指定的备用类
- python - 有没有办法让一个盒子在 vpython 中反射?
- c# - 存储库不会随着 UnitOfWorks 保存的更改而更新
- java - 来自适配器中 onActivityResult 的 SetText
- c# - 检测按钮是否在绘制的矩形框内
- c++ - 为什么我的析构函数异常没有被捕获
- amazon-web-services - Docker 容器更改时 Elastic Beanstalk 日志路径未更新
- php - 如何使用 android studio 将图像上传到服务器?