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

Retrofit2:能否循环使用@Part注解?多表单请求问题求助

Retrofit Multipart Dynamic @Part Solutions for Your Order List Request

Hey there, let's sort out this Retrofit multipart issue you're dealing with. Hardcoding those @Part("Order[0][...]") parameters is definitely not scalable—so I'll walk you through two solid dynamic solutions that should work perfectly with your backend's expected format.

Why Your Initial @PartMap Attempt Might Have Failed

First, let's quickly diagnose why your HashMap<String, RequestBody> didn't work. Chances are either:

  • The keys in your map weren't formatted exactly as the backend expects (like missing the Order[$index][...] structure), or
  • You didn't set the correct MediaType for your RequestBody instances (e.g., the backend expects plain text but you used a different type).

Solution 1: Fix & Use @PartMap (Cleanest Approach)

This is probably the simplest fix. You can dynamically build a Map<String, RequestBody> with the correct key structure, then pass it via @PartMap. Here's how to implement it:

Step 1: Update Your Retrofit Interface

Replace your hardcoded @Part parameters with a single @PartMap:

@Multipart
@POST("orders/total")
suspend fun orderList(@PartMap orderParams: Map<String, RequestBody>): Response<OrderModel>

Step 2: Build the Dynamic Part Map

Create a helper function to generate the map from your list of order items. First, define a data class to hold each order item's details:

data class OrderItem(val productId: String, val quantityId: String)

Then build the map by iterating over your items:

fun buildOrderPartMap(orderItems: List<OrderItem>): Map<String, RequestBody> {
    val partMap = mutableMapOf<String, RequestBody>()
    
    orderItems.forEachIndexed { index, item ->
        // Add product_id with the correct key format
        partMap["Order[$index][product_id]"] = 
            item.productId.toRequestBody(MediaType.get("text/plain"))
        
        // Add quantity_id similarly
        partMap["Order[$index][quantity_id]"] = 
            item.quantityId.toRequestBody(MediaType.get("text/plain"))
    }
    
    return partMap
}

Step 3: Call the Interface

When you need to make the request, just pass the generated map:

val myOrders = listOf(
    OrderItem("prod123", "qty456"),
    OrderItem("prod789", "qty012")
)

val response = apiService.orderList(buildOrderPartMap(myOrders))

Solution 2: Use MultipartBody.Builder (More Flexible)

If you prefer full control over the multipart body (e.g., adding files or other complex parts later), you can build the entire request body manually and pass it via @Body:

Step 1: Update the Interface

Change the interface to accept a MultipartBody:

@POST("orders/total")
suspend fun orderList(@Body multipartBody: MultipartBody): Response<OrderModel>

Step 2: Build the Multipart Body

Use MultipartBody.Builder to construct the request:

fun buildOrderMultipartBody(orderItems: List<OrderItem>): MultipartBody {
    val builder = MultipartBody.Builder()
        .setType(MultipartBody.FORM) // Required for multipart requests
    
    orderItems.forEachIndexed { index, item ->
        builder.addFormDataPart(
            "Order[$index][product_id]", 
            null, // Filename (null since this is text)
            item.productId.toRequestBody(MediaType.get("text/plain"))
        )
        builder.addFormDataPart(
            "Order[$index][quantity_id]", 
            null,
            item.quantityId.toRequestBody(MediaType.get("text/plain"))
        )
    }
    
    return builder.build()
}

Step 3: Make the Request

Just like before, pass the built body to your API service:

val response = apiService.orderList(buildOrderMultipartBody(myOrders))

Key Notes to Avoid Pitfalls

  • Match Media Types: Ensure the MediaType you use matches what your backend expects. If it accepts JSON for these fields, replace "text/plain" with "application/json".
  • Key Format: Double-check the key structure (Order[$index][product_id])—it must exactly match what the backend is looking for. A tiny typo here will cause the request to fail.

Both solutions eliminate the need for hardcoded @Part parameters and let you handle any number of order items dynamically.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 17:07:56