RetrofitWithCoroutineDemo icon indicating copy to clipboard operation
RetrofitWithCoroutineDemo copied to clipboard

Response body format

Open peerless2012 opened this issue 4 years ago • 5 comments

The Response body format in this example is :

{
    "type":"EN2ZH_CN",
    "errorCode":0,
    "elapsedTime":1,
    "translateResult":[
        [
            {
                "src":"Hello world",
                "tgt":"你好,世界"
            }
        ]
    ]
}

But usually this response body format is :

{
    "errorCode":0,
	"errorMsg":"",
	"result":{
	    "elapsedTime":1,
		"type":"EN2ZH_CN",
		"translateResult":[
			[
				{
					"src":"Hello world",
					"tgt":"你好,世界"
				}
			]
		]
	}
    
}

And the ApiResult type is result type, so how can i fix this ?

peerless2012 avatar Jan 23 '21 03:01 peerless2012

you can check this file

https://github.com/ShuangtaoJia/RetrofitWithCoroutineDemo/blob/main/app/src/main/java/com/jst/retrofitwithcoroutine/ui/main/api/TranslateApiService.kt

interface TranslateApiService {
    @FormUrlEncoded
    @POST("translate?doctype=json")
    suspend fun translate(@Field("i")i:String):ApiResult<Result>
}

data class Result(
    val type: String,
    val elapsedTime: Int,
    val translateResult: List<List<TranslateResult>>
) {
    data class TranslateResult(
        val src:String,
        val tgt:String
    )
}

object TranslateApi{
    val retrofitService: TranslateApiService by lazy { retrofit.create(TranslateApiService::class.java) }
}

the ApiResult type is not result type,it's a wrapper of successful or failed result ,the result type is Result,so you can change the content of Result to fit your json format

and you also need to edit the BusinessErrorInterceptor.kt file to parse the errorCode and errorMsg using your json format

https://github.com/ShuangtaoJia/RetrofitWithCoroutineDemo/blob/main/network/src/main/java/com/jst/network/interceptor/BusinessErrorInterceptor.kt

I explain the principle of this repository in this article,but it's in Chinese,maybe you can translate it.

https://blog.csdn.net/taotao110120119/article/details/110878525

ShuangtaoJia avatar Jan 25 '21 13:01 ShuangtaoJia

If i want to use the generic type of ApiResult as the result, do you have any idea ?

peerless2012 avatar Jan 26 '21 08:01 peerless2012

https://proandroiddev.com/suspend-what-youre-doing-retrofit-has-now-coroutines-support-c65bd09ba067

maybe this article can help you ,this is the basic of "Retrofit + Coroutine"

but this article not cover network error case.

ShuangtaoJia avatar Jan 26 '21 12:01 ShuangtaoJia

I solve my ploblem by change the generic type of ApiResultCallAdapter<T> to ApiResultCallAdapter<T: ApiResult<Any>>, and also change the ApiResult from scaled class to Class, the type i pass to ApiResultCallAdapter is ApiResult.

Also I think there is no need to parse the response code in BusinessErrorInterceptor , because we can process the response code and http code in delegate.onResponse, and process ioexception and other exception in delegate.onFailure.

That's what i do in my project .

Tanks a lot for your work.

peerless2012 avatar Jan 27 '21 06:01 peerless2012

I have a solution. Add the following code


sealed class ApiResult<out T> {
    data class Success<out T>(val d: T) : ApiResult<T>()
    data class Failure(val errorCode: Int, val errorMsg: String) : ApiResult<Nothing>()
}

val <T>ApiResult.Success<BaseBean<T>>.data: T
    get() {
        return d.data
    }

val <T>ApiResult.Success<BaseBean<T>>.errorMsg: String
    get() {
        return d.msg
    }

val <T>ApiResult.Success<BaseBean<T>>.errorCode: Int
    get() {
        return d.err
    }

SmilingBoy avatar Jan 27 '21 06:01 SmilingBoy