You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Retrofit解析JSON的offers字段并映射到Offers实体类?

解决Retrofit解析包含result和offers字段的JSON问题

你的核心问题是API返回的是包含result和offers的顶层对象,而非直接的Offers数组,同时数据类存在字段不匹配的情况,下面是分步解决方案:

1. 创建顶层响应数据类

先定义一个包裹整个API响应的数据类,对应返回的JSON结构:

data class OfferResponse(
    val result: Boolean,
    val offers: List<Offers>
)

2. 修正Offers数据类的字段匹配问题

你的数据类有3处和JSON字段不匹配,会导致解析失败,需调整:

  • JSON中lmd_id是字符串类型,你定义为Int会解析错误,改为String(后续使用时可再转Int)
  • JSON中smartLink是驼峰命名,数据类里smartlink大小写不一致,用@SerializedName映射
  • JSON中offer_text对应数据类的long_offer,同样用@SerializedName映射

修正后的代码:

import com.google.gson.annotations.SerializedName

data class Offers (
    val lmd_id: String,
    val store: String?,
    val merchant_homepage: String?,
    @SerializedName("offer_text")
    val long_offer: String?,
    val title: String?,
    val description: String?,
    val code: String?,
    val terms_and_conditions: String?,
    val categories: String?,
    val featured: String?,
    val publisher_exclusive: String?,
    val url: String?,
    @SerializedName("smartLink")
    val smartlink: String?,
    val image_url: String?,
    val type: String?,
    val offer: String?,
    val offer_value: String?,
    val status: String?,
    val start_date: String?,
    val end_date: String?
)

3. 修改DealsService接口

将返回类型从List<Offers>改为OfferResponse,对应完整的API响应结构:

interface DealsService {
    @GET("getOffers/?API_KEY=$api_key&incremental=1&format=json")
    suspend fun getOffers(): OfferResponse
}

4. 调整Fragment中的调用逻辑

现在需要先获取完整响应,再从中取出offers列表,同时添加异常处理避免崩溃:

val dealsService = DealsNetwork.getRetrofitClient().create(DealsService::class.java)

// 建议用viewLifecycleOwner的协程Scope,避免内存泄漏
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
    try {
        // 获取完整响应对象
        val response = dealsService.getOffers()
        // 提取offers列表
        val offersList = response.offers

        withContext(Dispatchers.Main) {
            val rvDealsAdapter = DealsListRecyclerAdapter(offersList, dealsViewModel)
            binding.rvDealsList.layoutManager = layoutManager
            binding.rvDealsList.adapter = rvDealsAdapter
        }
    } catch (e: Exception) {
        // 处理网络请求或解析错误,比如打印日志、提示用户
        e.printStackTrace()
        withContext(Dispatchers.Main) {
            // 可在此显示错误提示,比如Toast
        }
    }
}

额外注意事项

  • 确保api_key有效,避免因权限问题返回错误响应
  • 如果必须将lmd_id作为Int使用,可在数据类中保留val lmd_id: Int,Gson会自动将合法数字字符串转为Int,但遇到非数字值会崩溃,需谨慎
  • 避免直接创建CoroutineScope,优先使用viewLifecycleOwner.lifecycleScope或viewModelScope,防止内存泄漏

内容的提问来源于stack exchange,提问作者Kidus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 18:23:18