改造 API 调用 returns 空

Retrofit API call returns 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
)

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)
    }
}

Repository(发现错误的地方):

@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 with undefined key.

首先,创建一个自定义 Json 反序列化器。因为这里你的数据 api 有一个未定义的键。在这里,我将使用自定义 Json 反序列化器创建 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()的return类型改为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")
    }
}