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

Android Kotlin中Retrofit读取API时productsDetalys字段为null的问题

问题:Retrofit解析JSON时productsDetalys字段始终返回null

我正在Android Kotlin中使用Retrofit读取API返回的JSON数据,想要获取productsDetalys下的内容。目前可以正常读取orders_id、customers_id等字段,但productsDetalys始终返回null。

API返回的JSON数据

{"body": [
    {
      "orders_id": "52",
      "customers_id": "1",
      "customers_name": "Nida Verkkopalvelu",
      "customers_company": "Etäisyys 2.3 km",
      "customers_street_address": "Suoratie 40",
      "customers_suburb": "",
      "customers_city": "Porvoo",
      "customers_postcode": "06100",
      "customers_state": "",
      "customers_country": "Finland",
      "customers_telephone": "09444744",
      "customers_email_address": "test@nida.fi",
      "delivery_name": "Nida Verkkopalvelu",
      "delivery_company": "Etäisyys 2.3 km",
      "delivery_street_address": "Suoratie 40",
      "delivery_suburb": "",
      "delivery_city": "Porvoo",
      "delivery_postcode": "06100",
      "delivery_state": "",
      "delivery_country": "Finland",
      "payment_method": "Paytrail - Online Payment",
      "payment_module_code": "paytrail",
      "shipping_method": "Per Item (Best Way)",
      "shipping_module_code": "item",
      "coupon_code": "",
      "date_purchased": "2023-04-10 10:01:49",
      "orders_status": "2",
      "currency": "EUR",
      "currency_value": "1.000000",
      "order_total": "55.00",
      "order_tax": "0.00",
      "language_code": "en",
      "comments": "",
      "productsDetalys": [
        [
          {
            "orders_products_id": "111",
            "products_name": "Book",
            "products_price": "0.00",
            "final_price": "52.50",
            "products_tax": "0.00",
            "products_quantity": 1,
            "products_options": "Version",
            "products_options_values": "Book Hard Cover",
            "options_values_price": "52.50"
          }
        ]
      ]
    }
  ],
  "itemCount": 1
}

当前使用的数据模型类

OrderDetailsModelClass

data class OrderDetailsModelClass(
    val body: List<BodyOrderDetails>,
    val itemCount: Int
)

BodyOrderDetails

data class BodyOrderDetails(
    val comments: String,
    val coupon_code: String,
    val currency: String,
    val currency_value: String,
    val customers_city: String,
    val customers_company: String,
    val customers_country: String,
    val customers_email_address: String,
    val customers_id: String,
    val customers_name: String,
    val customers_postcode: String,
    val customers_state: String,
    val customers_street_address: String,
    val customers_suburb: String,
    val customers_telephone: String,
    val date_purchased: String,
    val delivery_city: String,
    val delivery_company: String,
    val delivery_country: String,
    val delivery_name: String,
    val delivery_postcode: String,
    val delivery_state: String,
    val delivery_street_address: String,
    val delivery_suburb: String,
    val language_code: String,
    val order_tax: String,
    val order_total: String,
    val orders_id: String,
    val orders_status: String,
    val payment_method: String,
    val payment_module_code: String,
    val ProductsDetalys: List<List<ProductsDetalys>>,
    val shipping_method: String,
    val shipping_module_code: String
)

ProductsDetalys

data class ProductsDetalys(
    val final_price: String,
    val options_values_price: String,
    val orders_products_id: String,
    val products_name: String,
    val products_options: String,
    val products_options_values: String,
    val products_price: String,
    val products_quantity: Int,
    val products_tax: String
)

Retrofit接口与MainActivity实现

ProductDetailsApi接口

interface ProductDetailsApi {
    @GET()
    fun getProductDetails() : Call<OrderDetailsModelClass>
}

MainActivity代码

class MainActivity : AppCompatActivity() {

   lateinit var orderDetailsList: List<BodyOrderDetails>
   lateinit var productsDetailsList: List<ProductsDetalys>

   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_order_details)

        val retrofitProductDetails = Retrofit.Builder()
            .baseUrl("https://pizzapalvelu.fi/158a/")
            .addConverterFactory(GsonConverterFactory.create()).build()

        val apiProductDetailsList = retrofitProductDetails.create(ProductDetailsApi::class.java)

        apiProductDetailsList.getProductDetails().enqueue(object :
            Callback<OrderDetailsModelClass> {

            override fun onResponse(
                call: Call<OrderDetailsModelClass>,
                response: Response<OrderDetailsModelClass>
            ) {
                
                orderDetailsList = response.body()?.body ?: orderDetailsList
                //此处可读取其他数据,但打印orderDetailsList时,productsDetalys为null

            }

            override fun onFailure(call: Call<OrderDetailsModelClass>, t: Throwable) {
                t.message?.let { Log.e("mesaj", it) }
            }
        })

   }
}

解决方案

核心错误原因

JSON中的字段是productsDetalys(首字母小写p),但你在BodyOrderDetails模型类中定义的字段是ProductsDetalys(首字母大写P)。Gson默认会严格匹配字段名的大小写,导致无法映射该字段,所以返回null。

修正步骤

1. 修正模型类字段名

将BodyOrderDetails中的ProductsDetalys改为productsDetalys,保持和JSON字段名完全一致:

data class BodyOrderDetails(
    // 其他字段保持不变
    val productsDetalys: List<List<ProductsDetalys>>,
    // 其他字段保持不变
)

2. 增加空安全处理(可选但推荐)

为了避免因API返回该字段为空导致的崩溃,可以将字段声明为可空类型,并设置默认值:

data class BodyOrderDetails(
    // 其他字段保持不变
    val productsDetalys: List<List<ProductsDetalys>>? = emptyList(),
    // 其他字段保持不变
)

3. 正确获取产品详情数据

在onResponse中可以这样获取productsDetalys的数据:

override fun onResponse(
    call: Call<OrderDetailsModelClass>,
    response: Response<OrderDetailsModelClass>
) {
    response.body()?.let { orderDetails ->
        orderDetailsList = orderDetails.body
        // 获取第一个订单的产品详情
        orderDetailsList.firstOrNull()?.productsDetalys?.let { nestedList ->
            // 因为是嵌套列表,需要取出内层列表的元素
            productsDetailsList = nestedList.flatten()
            // 现在productsDetailsList就是所有产品详情的列表,可以使用它做后续操作
            productsDetailsList.forEach { product ->
                Log.d("Product", "Name: ${product.products_name}, Price: ${product.final_price}")
            }
        }
    }
}

4. 补充Retrofit接口的@GET路径

注意你的ProductDetailsApi接口中@GET()没有指定具体路径,需要补充完整的API端点,比如:

interface ProductDetailsApi {
    @GET("your-api-endpoint-path") // 替换为实际的API路径
    fun getProductDetails() : Call<OrderDetailsModelClass>
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:25:00