如何解析动态键JSON并创建对应数据类?自定义反序列化方案
解析动态键JSON的Gson实现方案
你的API返回的JSON是外层为动态字符串键的对象结构,每个键对应固定格式的数据。下面直接给出两种可行的解析方案:
步骤1:定义基础数据类
先对应JSON里的嵌套结构定义数据类:
// 对应content数组里的单个项 data class ContentItem( val id: Long ) // 每个动态键对应的完整数据结构 data class EntryData( val id: String, val content: List<ContentItem> )
方式一:直接解析为Map(最简方案)
不需要自定义反序列化逻辑,直接把JSON解析成Map<String, EntryData>即可:
builder.build().newCall(request).execute().use { response -> if (response.isSuccessful) { val responseBody = response.body?.string() if (!responseBody.isNullOrBlank()) { // 用TypeToken明确泛型类型 val readings: Map<String, EntryData> = gson.fromJson( responseBody, object : TypeToken<Map<String, EntryData>>() {}.type ) // 遍历处理每个动态键对应的内容 readings.forEach { (key, entry) -> println("键:$key,条目ID:${entry.id},首个内容ID:${entry.content.firstOrNull()?.id}") } } else { println("Response body is empty.") } } else { println("Request failed with code: ${response.code}") } }
方式二:封装为自定义类(如需结构化封装)
如果不想直接用Map,可封装成自定义响应类,配合Gson自定义反序列化:
1. 定义自定义响应类
data class ApiResponse( val entries: Map<String, EntryData> )
2. 实现自定义反序列化器
class ApiResponseDeserializer : JsonDeserializer<ApiResponse> { override fun deserialize( json: JsonElement, typeOfT: Type, context: JsonDeserializationContext ): ApiResponse { val jsonObject = json.asJsonObject val entries = mutableMapOf<String, EntryData>() // 遍历所有动态键并解析为EntryData jsonObject.entrySet().forEach { entry -> val entryData = context.deserialize<EntryData>(entry.value, EntryData::class.java) entries[entry.key] = entryData } return ApiResponse(entries) } }
3. 注册反序列化器并解析
// 初始化带自定义反序列化器的Gson实例 val gson = GsonBuilder() .registerTypeAdapter(ApiResponse::class.java, ApiResponseDeserializer()) .create() // 调用API并解析 builder.build().newCall(request).execute().use { response -> if (response.isSuccessful) { val responseBody = response.body?.string() if (!responseBody.isNullOrBlank()) { val apiResponse = gson.fromJson(responseBody, ApiResponse::class.java) // 处理封装后的entries apiResponse.entries.forEach { (key, entry) -> println("键:$key,条目ID:${entry.id}") } } else { println("Response body is empty.") } } else { println("Request failed with code: ${response.code}") } }
注意事项
- 确保项目已引入Gson依赖(比如Gradle中添加
implementation 'com.google.code.gson:gson:2.10.1') - 处理
content数组时,若数组可能为空,建议用firstOrNull()避免空指针异常
内容的提问来源于stack exchange,提问作者Daviti Gogochishvili
相关产品推荐
相关产品推荐

