使用改造对 JSON 数据建模的更有效方法 - Kotlin
Posted
技术标签:
【中文标题】使用改造对 JSON 数据建模的更有效方法 - Kotlin【英文标题】:More efficient way to model JSON data using retrofit - Kotlin 【发布时间】:2021-10-25 03:18:48 【问题描述】:我要使用的数据有这样的结构:
"1":
"id": 1,
"name": "Bulbasaur"
,
"2":
"id": 2,
"name": "Ivysaur"
,
"3":
"id": 3,
"name": "Venusaur"
注意: 标记每个对象的数字与神奇宝贝的 id 匹配,而不是神奇宝贝的数量
我的问题是,当我尝试为此创建数据类时,它最终会为每个对象创建一个数据类。没有一个数据类适合每个对象。我相信这是由于标记对象(神奇宝贝)的数字对于每个对象都不同。
有没有一种方法可以将这些数据格式化为一个或两个数据类,而不是超过 800 个?
理想情况下,我希望数据具有这样的结构,但运行时不起作用。
data class ReleasedPokemonModel(
val id: Int,
val name: String
)
【问题讨论】:
如果我的评论能帮助你解决问题,希望你能接受我的回答。谢谢! 【参考方案1】:当使用这种特殊情况将 Json 解析为 Object 时,您应该自己自定义 Json Deserializer。
这里我使用 Gson 库将 Json 解析为 Object。
首先,使用 Gson 创建一个自定义的 Json Deserializer。如下:
PokemonResponse.kt
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)
接下来我将创建一个GsonConverterFactory
,以便我可以addConvertFactory
进行改造。
val gsonConverterFactory = GsonConverterFactory.create(GsonHelper.create())
现在我将添加改造。
val retrofit = Retrofit.Builder()
// Custom your Retrofit
.addConverterFactory(gsonConverterFactory) // Add GsonConverterFactoty
.build()
最后在 ApiService 中,您的响应现在将返回类型 PokemonResponse
。
interface ApiService
@GET("your_link")
suspend fun getGenres(): PokemonResponse
【讨论】:
【参考方案2】:问题是那里没有 JSON 数组。它实际上是一个 JSON 对象,每个口袋妖怪都被列为一个属性。我建议您事先重新格式化 JSON,使其看起来像这样:
[
"id": 1,
"name": "Bulbasaur"
,
"id": 2,
"name": "Ivysaur"
,
"id": 3,
"name": "Venusaur"
]
然后你可以这样建模:
data class ReleasedPokemonModel(
val id: Int,
val name: String
)
data class Response(
val items: List<ReleasedPokemonModel>
)
See more here.
And see here for discussion about reformatting the data before handing it to Retrofit.
【讨论】:
【参考方案3】:您可以使用 Map 来存储密钥,如下所示
data class PokemonResponse(
val pokemonMap:Map<String,ReleasedPokemonModel>
)
data class ReleasedPokemonModel(
val id: Int,
val name: String
)
【讨论】:
以上是关于使用改造对 JSON 数据建模的更有效方法 - Kotlin的主要内容,如果未能解决你的问题,请参考以下文章