Issue
I've been trying to make a POST with Retrofit 2 and Moshi but I've been unable to get it to work. My data classes look like this:
data class Order(
val items: List<Item>?,
val customerName: String,
val customerPhoneNo: String,
val customerAddress: String,
val note: String
)
data class Item(
val productUid: String,
var quantity: Int
)
The interface looks like this
interface ProductService {
@POST("/api/order/saveorder")
suspend fun postProds(
@Field("customerName") customerName: String,
@Field("customerPhoneNo") customerPhone: String,
@Field("customerAddress") address: String,
@Field("note") customerNote:String,
@Field("items") orderItems: List<Item>
): Response<Order>
@GET("/api/product/allproducts")
suspend fun getProds(): Response<List<ProdsItem>>
}
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
object Network {
private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi)
.asLenient()
)
.build()
object ProdsApi {
val retrofitService: ProductService by lazy {
retrofit.create(ProductService::class.java)
}
}
}
The postProds fun is called like this:
suspend fun sendOrder(order: Order) {
withContext(Dispatchers.Main){
try {
val orderResponse = Network.ProdsApi.retrofitService.postProds(
order.customerName,
order.customerPhoneNo,
order.customerAddress,
order.note,
order.items )
}
catch (e: Exception) {
Timber.e(e)
}
}
}
Trying to POST this way keeps yielding this response:
Response{protocol=h2, code=400, message=, url=
However, I tried converting the Order object to json directly in my viewModel as follows:
val moshi: Moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val jsonAdapter: JsonAdapter<Order> = moshi.adapter(Order::class.java)
val jsonString = jsonAdapter.toJson(customerOrder)
Timber.d(jsonString)
I then tested the generated jsonString on Postman and got a 200 response.
I need some help figuring out what I'm doing wrong in my code, please.
Solution
In postman, you are sending data in the body of the request. But in your code, it is going as key-value params. Try to send it in the body from your code. Try below snippet.
Update your Order Data class:
@JsonClass(generateAdapter = true)
data class Order(
@Json(name = "items")
val items: List<Item>?,
@Json(name = "customerName")
val customerName: String,
@Json(name = "customerPhoneNo")
val customerPhoneNo: String,
@Json(name = "customerAddress")
val customerAddress: String,
@Json(name = "note")
val note: String
)
@JsonClass(generateAdapter = true)
data class Item(
@Json(name = "productUid")
val productUid: String,
@Json(name = "quantity")
var quantity: Int
)
Now the ProductService Interface:
interface ProductService {
@POST("/api/order/saveorder")
suspend fun postProds(
@Body request: Order
): Response<Order>
@GET("/api/product/allproducts")
suspend fun getProds(): Response<List<ProdsItem>>
}
Now Pass the request object in your function call:
suspend fun sendOrder(order: Order) {
withContext(Dispatchers.Main){
try {
val orderResponse = Network.ProdsApi.retrofitService.postProds(order)
}
catch (e: Exception) {
Timber.e(e)
}
}
}
Answered By - Alpha 1
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.