Search code examples
androidandroid-studiokotlinretrofit2okhttp

Retrofit response body filed retun null, but logging interceptor showing full response in logact


I am using retrofit2.6.2 for api call. LoggingInterceptor showing full response in logcat but retrofit response body return null. I didn't figure out where is my problem.

My json data schema is

{
   "error":false,
   "msg":"Banner Found",
   "id":"9",
   "activity":"VipPremium1",
   "imageUrl":"https:\/\/1.bp.blogspot.com\/-Kh3RQlJH7Xw\/X-1mIPi7_HI\/AAAAAAAAFME\/Y2bCnU5odngcdDT83uC9QwUr7IGJdTDfACLcBGAsYHQ\/s2616\/COMPRESSED_IMG_1609393684674.jpg",
   "actionUrl":"https:\/\/www.youtube.com\/watch?v=ukJX5ZgJec4",
   "actionType":1,
   "visible":true
}

Model Class BannerRes

data class BannerRes(
    @SerializedName("actionType")
    val actionType: Int?,
    @SerializedName("actionUrl")
    val actionUrl: String?,
    @SerializedName("activity")
    val activity: String?,
    @SerializedName("error")
    val error: Boolean?,
    @SerializedName("id")
    val id: String?,
    @SerializedName("imageUrl")
    val imageUrl: String?,
    @SerializedName("msg")
    val msg: String?,
    @SerializedName("visible")
    val visible: Boolean?
)

Api Interface

@GET("api/helper.getBanner.php")
    suspend fun getBanner(
        @Query("bannerName") bannerName: String,
    ): Response<BannerRes>

Api call done here

private fun loadPremiumBanner() {
       
        Coroutines.main {
           val res =  viewModel.getBanner("VipPremium1")
            Log.d("Response", res.body()!!.msg!!) 
        }
    }

When I print response body using

 Log.d("Response", Gson().toJson(res.body()))

It shows the the response in logcat, Logcat

{"error":false,"msg":"Banner Found","id":"9","activity":"VipPremium1","imageUrl":"https://1.bp.blogspot.com/-Kh3RQlJH7Xw/X-1mIPi7_HI/AAAAAAAAFME/Y2bCnU5odngcdDT83uC9QwUr7IGJdTDfACLcBGAsYHQ/s2616/COMPRESSED_IMG_1609393684674.jpg","actionUrl":"https://www.youtube.com/watch?v\u003dukJX5ZgJec4","actionType":1.0,"visible":true}

but when access res.body()!!.msg It shows null.

Retrofit Setup

companion object {

        @Volatile
        private var myApiInstance: MyApi? = null
        private val LOCK = Any()

        operator fun invoke() = myApiInstance ?: synchronized(LOCK) {
            myApiInstance ?: createClient().also {
                myApiInstance = it
            }
        }

        private fun createClient(): MyApi {
            val AUTH: String = "Basic ${
                Base64.encodeToString(
                    ("${BuildConfig.USER_NAME}:${BuildConfig.USER_PASSWORD}").toByteArray(),
                    Base64.NO_WRAP
                )
            }"



            val interceptor = run {
                val httpLoggingInterceptor = HttpLoggingInterceptor()
                httpLoggingInterceptor.apply {
                    httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
                }
            }


            val okHttpClient: OkHttpClient = OkHttpClient.Builder()
                .callTimeout(10,TimeUnit.SECONDS)
                .addInterceptor(interceptor)
                .addInterceptor { chain ->
                    val original: Request = chain.request()
                    val requestBuilder: Request.Builder = original.newBuilder()
                        .addHeader("Authorization", AUTH)
                        .method(original.method, original.body)
                    val request: Request = requestBuilder.build()
                    chain.proceed(request)
                }
                .build()

            val gsonBuilder = GsonBuilder()
            gsonBuilder.setLenient()
            val gson = gsonBuilder.create()

            return Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addConverterFactory(ScalarsConverterFactory.create())
                .client(okHttpClient)
                .build()
                .create(MyApi::class.java)
        }


    }

Solution

  • I resolved this issue by adding kotlin model data class member filed default value. I don't know what is the reason behind this,

    Old data class

    data class BannerRes(
        @SerializedName("actionType")
        val actionType: Int?,
        @SerializedName("actionUrl")
        val actionUrl: String?,
        @SerializedName("activity")
        val activity: String?,
        @SerializedName("error")
        val error: Boolean?,
        @SerializedName("id")
        val id: String?,
        @SerializedName("imageUrl")
        val imageUrl: String?,
        @SerializedName("msg")
        val msg: String?,
        @SerializedName("visible")
        val visible: Boolean?
    )
    

    Modified or data class with member field default value which fix my problem

    data class BannerRes(
        @SerializedName("error") var error : Boolean = true,
        @SerializedName("msg") var msg : String? = null,
        @SerializedName("id") var id : String? = null,
        @SerializedName("activity") var activity : String? = null,
        @SerializedName("imageUrl") var imageUrl : String? = null,
        @SerializedName("actionUrl") var actionUrl : String? = null,
        @SerializedName("actionType") var actionType : Int = 0,
        @SerializedName("visible") var visible : Boolean = false
        )