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.
Related
I have a problem with handling responses in YAML format in Retrofit. Until now I only handled the response body in JSON format or plain text. For these types, I always have prepared converters like gson, jackson for JSON and scalars for plain text. I found repository with all converters: retrofit-convertes.
In the documentation is a short mention that I need to create my own converter for this type.
If you need to communicate with an API that uses a content-format that Retrofit does not support out of the box (e.g. YAML, txt, custom format) or you wish to use a different library to implement an existing format, you can easily create your own converter. Create a class that extends the Converter.Factory class and pass in an instance when building your adapter.
Sadly, I don't see any tutorial on how to create such a converter. Is there any documentation explaining how to do this or is there any other option to handle such a case?
In your case you can use Jackon with yaml data formats.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("<your base url>")
.addConverterFactory(JacksonConverterFactory.create(new ObjectMapper(new YAMLFactory())))
.build();
For more informating check the following links:
https://github.com/square/retrofit/tree/master/retrofit-converters/jackson
https://github.com/FasterXML/jackson-dataformats-text/tree/master/yaml
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);
I am trying to make a simple weather app using retrofit library. I want the city name to be dynamic. This is what i have done so far:
full url:
http://api.openweathermap.org/data/2.5/forecast/daily?q=dhaka&cnt=7&appid=1111
base url:
http://api.openweathermap.org/
in the main activity
LinkedHashMap<String,String>data=new LinkedHashMap<>();
data.put("q",targetCity);
data.put("cnt",Integer.toString(7));
data.put("appid",getString(R.string.api_key));
Call<WeatherResponse>weatherResponseCall=weatherServiceApi.getAllWeatherReport(data);
and in my api interface:
#GET("data/2.5/forecast/daily?")
Call<WeatherResponse>getAllWeatherReport(#QueryMap LinkedHashMap<String,String>data);
I am neither getting any error, nor any response data.
Please help.
You aren't executing the call function...
WeatherResponse response = call.execute().body();
If I were you, I would try using a ResponseBody from okhttp to get the data returned. Then using response.string() you can see what's retrieved from the request.
Or, to log the body data of each request/response you should add this interceptor when building your Retrofit object:
OkHttpClient client = httpClient.addInterceptor(interceptor.setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
Retrofit retrofit = builder.client(client).build();
return retrofit.create(serviceClass);
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)
)
)