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)
)
)
Related
I have a legacy project that is using both jackson and gson deserializers. I would like to use retrofit to parse data from either. However the problem is that neither the JacksonConverterFactory or GsonConverterFactory return null for the responseBodyConverter. IE here is the jackson impl:
#Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
JavaType javaType = mapper.getTypeFactory().constructType(type);
ObjectReader reader = mapper.readerFor(javaType);
return new JacksonResponseBodyConverter<>(reader);
}
I would like to use Jackson in the case where I have registered a deserializer, ie:
val module = SimpleModule()
module.addDeserializer(User::class.java, UserDeserializer())
val objectMapper = ObjectMapper()
objectMapper.registerModule(module)
val converterFactory = JacksonConverterFactory.create(objectMapper)
So in this case if a user is being deserialized, use Jackson, otherwise skip and look at next registered converter factory, in this case gson.
I get that since JacksonConverterFactory never returns null, such that the converter factory will be skipped I would need to write my own ConverterFactory impl. I am looking for a way in jackson to look at the mappers module and determine if there is a customer deserializer. However form the docs and public API I cannot seem to find the registered deserializers.
Am I going about this the right way?
I am not sure what you mean but as far as I understood you want to use both of the converter factories and customize them up to your liking. If that is the case, you can take a look at this: https://www.baeldung.com/jackson-vs-gson.
Hope that could help.
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.
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.
I struggled with this problem in the last hours and I looked for a guide.
I have an update request that I want to write in a generic way, which means that I would like to get a JSON of any kind, like a bag of property, and be able to work with it later in the application.
The problem I'm facing is that whenever I try to get it as JSON or String (and not as Model or ResponseBody) the app crashes. I think the arrest is due to decoding based on what I see.
This is the Retrofit builder.
public Retrofit getRetrofit(OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl("https://reqres.in/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(MoshiConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
return retrofit;
}
The REST interface is super simple.
public interface IRestService {
#GET("api/users?page=2")
Observable<String> queryPage();
}
I also tried to debug this issue, and I added my logger interceptor, that obviously does not work, and I have no idea why:
public OkHttpClient getOkHttpClient(Interceptor requestInterceptor) {
// HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
// loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
HttpLoggingInterceptor loggingInterceptor =
new HttpLoggingInterceptor((msg) -> {
Log.d(HttpLoggingInterceptor.class.toString(), msg);
});
//loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
LoggingInterceptor customLoggingInterceptor = new LoggingInterceptor();
return new okhttp3.OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT_IN_MS, TimeUnit.MILLISECONDS)
.addInterceptor(requestInterceptor)
.addInterceptor(loggingInterceptor)
.addInterceptor(customLoggingInterceptor)
.build();
}
Please let me know if there is anything I am doing wrong in getting the JSON out in a generic form, without a model.
And it would also be a great help if I could get some advice on how to debug this kind of problem, since the logger did not register anything in Android Studio.
Sorry if none of these questions is silly, but I've just started building my first app in Android. I have experience in many other languages.
Instead of using String for your Observable in the service(interface), use Object as the type. And when you get the data, you can always use Gson().toJson(body.toString()) to convert it to the string. Also, most probably your app is crashing for String because you don't have the correct converter factory (Scalar Factory). You can check this for the same.
From server send Json, but Retrofit2 response is xml.
I've found a solution in this link.
retrofit solution
But this solution is retroft not retrofit2.
Use POJO Generator Plugin for custom converter response from JSON or XML, with it you can post JSON with XML response
and usage :
.setConverter(new MixedConverter(new SimpleXMLConverter(), new GsonConverter(gson)));
and use as in this
Use a custom converter with both JSON and XML converters as in this answer of the question that you referenced in the question. Then use that converter to create Retrofit instance.
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(new MixedConverter(new SimpleXMLConverter(), GsonConverterFactory.create()))
.build();
ApiService apiService = retrofit.create(ApiService.class);