Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REQ] [kotlin][jvm-retrofit2] Add handling if responseBody is empty string #14982

Closed
dylan-kwon opened this issue Mar 17, 2023 · 2 comments
Closed

Comments

@dylan-kwon
Copy link
Contributor

dylan-kwon commented Mar 17, 2023

Is your feature request related to a problem? Please describe.

JsonParser throws an exception when ResponseBody is an empty string. (In my case I use kotlinx_serialization.)
square/retrofit#1554

Describe the solution you'd like

this case we need a way to handle empty strings.

Describe alternatives you've considered

Add [pre]converterFactory which can be called first in retrofitBuilder inside ApiClient. There is already converterFactory but it is not available in this case because it is added last.

private val retrofitBuilder: Retrofit.Builder by lazy {
        Retrofit.Builder()
            .baseUrl(baseUrl)

            ////////////  add  ////////// 
            .apply {
                if (preConverterFactory != null) {
                    addConverterFactory(preConverterFactory)
                }
            }
            ///////////////////////////////

            .addConverterFactory(ScalarsConverterFactory.create())
            .addConverterFactory(kotlinxSerializationJson.asConverterFactory("application/json".toMediaType()))
            .apply {
                if (converterFactory != null) {
                    addConverterFactory(converterFactory)
                }
            }
    }

This allows you to add converters to suit your project's needs.
(In my case, adding NullOnEmptyConverterFactory can solve the problem.)

class NullOnEmptyConverterFactory : Converter.Factory() {
    override fun responseBodyConverter(
        type: Type,
        annotations: Array<out Annotation>,
        retrofit: Retrofit
    ): Converter<ResponseBody, *> {
        val delegate: Converter<ResponseBody, *> = retrofit.nextResponseBodyConverter<Any?>(
            this, type, annotations
        )
        return Converter<ResponseBody, Any?> { body ->
            when (body.contentLength() == 0L) {
                true -> null
                else -> delegate.convert(body)
            }
        }
    }
}

This way, you can handle the response to suit your own requirements.

@wing328
Copy link
Member

wing328 commented Mar 20, 2023

can you please file a PR with the suggested fix when you've time?

@eriknyk
Copy link

eriknyk commented May 6, 2023

@dylan-kwon did you test it?
I've tested in retrofit v2.9.0 and contentLegth() is always -1,
and it makes sense, since it will be set only when the response body is consumed by calling [ResponseBody instance].bytes() or [ResponseBody instance].byteString()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants