I have Retrofit2 and Moshi inside my Android project for read json response i receive from some webservice.
I have noticed that i'm not able to read correctly accented letters inside json response, for example if a json field value contains
ü
that letter is parsed as
�
This is how i initialize Retrofit (i'm using dagger)
#Provides
#Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl(BASEURL)
.addConverterFactory(
MoshiConverterFactory.create(
Moshi.Builder().add(SingleToArrayAdapter.INSTANCE).build()
).asLenient()
)
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.client(okHttpClient)
.build()
}
And SingleToArrayAdapter is a custom adapter.
Related
I'm learning Coroutines of Kotlin and I'm a beginner of Retrofit.
The Code A is from the artical.
It seems that Retrofit get data from local server http://localhost/, I havn't run local web server.
Where does Retrofit get data ?
Code A
private val service: MainNetwork by lazy {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(SkipNetworkInterceptor())
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
retrofit.create(MainNetwork::class.java)
}
fun getNetworkService() = service
/**
* Main network interface which will fetch a new welcome title for us
*/
interface MainNetwork {
#GET("next_title.json")
suspend fun fetchNextTitle(): String
}
Itself!
If you look at the code: .addInterceptor(SkipNetworkInterceptor()). Interceptors process every call that is made through Retrofit.
Some people use it to log data about calls for debugging. Some people use it to automatically provide authorization tokens.
In this case, it is providing fake data.
You can read about that here:
https://github.com/googlecodelabs/kotlin-coroutines/blob/master/coroutines-codelab/finished_code/src/main/java/com/example/android/kotlincoroutines/util/SkipNetworkInterceptor.kt
You should write this IP which is the equivalent of localhost in base url.
val retrofit = Retrofit.Builder()
.baseUrl("http://10.0.2.2:3000/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
But you should check your port number on localhost. After checking, you should add your port number to the part that says 3000. Replace with 3000.
I am using retrofit to to send data as json to my server.
Retrofit.Builder()
.client(client)
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
Everything works fine, but when i try to send a large string (base64 encoded picture) inside of a class, the json converter adds multiple "\n" to the string.
picture":"/9j/4AAQSkZJRgA...QEBAQEBAQEBAQEB \n AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB \n A...
This is how send the request:
#POST("testservice")
fun test(#Body testBody: TestBody): Call<TestResponse>
Call:
testService.test(testBody).enqueue(...)
Does anyone have a solution to the problem?
The service works perfectly if I don't send the picture.
I am expecting both json and xml response in my app. Retrofit 2.0 allows you to add multiple Converter Factories for such situations.
But it seems the order is of utmost importance here. Adding JacksonConverterFactory above SimpleXmlConverterFactory makes Retrofit accept only Json response and throws exception when it encounters XML and vice versa.
Below is a code snippet of how to add multiple addConverterFactory to your Retrofit Builder.
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
.addConverterFactory(SimpleXmlConverterFactory.create())
<<< edit
Changed the above code to this, but still not working:
return new Retrofit.Builder()
.client(clientBuilder.build())
.baseUrl(BuildConfig.API_ENDPOINT)
.addCallAdapterFactory(unAuthorizedHandlingCallAdapterFactory)
.addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
.addConverterFactory(new QualifiedTypeConverterFactory(JacksonConverterFactory.create(objectMapper), SimpleXmlConverterFactory.create()))
.build();
edit2
Adding the response type was the key #GET("/") #Xml
You can combine multiple Converter Factories into a single Converter Factory, check this example from retrofit samples.
Recently I switched to MoshiConverterFactory from GSONConverterFactory. Every thing s working fine except the one call. Like other API calls here also I am using #Body annotation but I am getting this error
java.lang.IllegalArgumentException: Unable to create #Body converter for class
my request class :
data class DemoRequest(
val emailId: String? = null,
val demoData: List<DemoDomain?>? = null,
val userName: String? = null
)
One more thing here to mention that with GSONConverterFactory it is working fine but as I switched to MoshiConverterFactory it is throwing error.
retrofitVersion = '2.3.0'
service interface:
#POST("call/api")
fun sendToServer(#Body request: DemoRequest):retrofit2.Call<RemoteResponse>
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(MoshiConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
UPDATE-------------
I was sending Date object in request so I need to use custom adapter and it is working fine now
Did you remember to change to MoshiConverterFactory when you build Retrofit?
Retrofit.Builder().baseUrl(...).addConverterFactory(MoshiConverterFactory.create()).build()
Also, the latest version of Retrofit is 2.5.0 so you could try upgrading and make sure your converter is also the same version.
I am just simply trying to use retrofit to perform my rest api calls. The issue that I am facing is that when parsing the json, some of the key fields contain dots. For example:
{ "data": { "name.first": "first name"} }
Is it possible to configure Retrofit (or GsonConverter) to be able to handle this and how do I go about doing so?
This is neither Retrofit nor the GsonConverter's responsibility but rather Gson which sits underneath doing the actual JSON (de)serialization.
You can use Gson's #SerializedName annotation to work around names which cannot be represented in Java:
#SerializedName("name.first")
public final String firstName;
if you are using Moshi as your JSON convertor, replace it with GSON convertor factory.
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create()) //add this
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.client(
getOkHttpClient(
NetworkModule.networkModule.context,
enableNetworkInterceptor(baseUrl)
)
)