Trouble get special character in retrofit 2 and gson - android

I'm trying to get a json list from a web service.
This is the json string return by server :
[{"categoryName":"Política"},{"categoryName":"Economía"},{"categoryName":"Cultura"},{"categoryName":"Deportes"}
The problem is converting in to the POJO. The special characters (í) it's appear like "Pol�tica".
This is the retrofit call function :
#GET("categories")
public Call<List<CategoryPojo>> getCategorias(#Query("sitename") String site)
this is the callback function:
Call<List<CategoryPojo>> call = restservice.getApiService().getCategorias(medio);
try {
call.enqueue(new Callback<List<CategoryPojo>>() {
#Override
public void onResponse(Call<List<CategoryPojo>> call, Response<List<CategoryPojo>> response) {
List<CategoryPojo> categories = response.body();
if (listener != null)
listener.onDataLoaded(categories);
}
#Override
public void onFailure(Call<List<CategoryPojo>> call, Throwable throwable) {
Log.e("Retrofit Error", throwable.getMessage());
}
});
this is the POJO:
public class CategoryPojo implements Serializable{
public CategoryPojo() { }
#SerializedName("categoryName")
private String name;
public String getName()
{
return this.name;
}
}
The result of the request to the Web services, (output in browser) is :
[{"categoryName":"Política"},{"categoryName":"Economía"},{"categoryName":"Cultura"},{"categoryName":"Deportes"},{"categoryName":"Salud"},{"categoryName":"Ciencia y Tecnología"},{"categoryName":"Medio Ambiente"},{"categoryName":"Medios"},{"categoryName":"Militar e Inteligencia"},{"categoryName":"Sociedad"}]
So, the return json has a good encoding...i think that maybe is about the way retrofit read the response.
I'm using retrofit-2.0.2, gson-2.6.1, converter-gson-2.0.2, okhttp-3.2.0.
Any help? please

You should check Content-type in the response headers. Look for the charset value and try to change that on the backend side to application/josn;charset=UTF-8. That worked for me.

Related

Check which type of data is coming as response using Retrofit

As I'm using Retrofit, I've designed all the POJOs and it was working flawlessly. API is designed in such a way that it will send the required data if the data is of current date or of future dates but not for past dates. In the response, I'll get a JSON response contains a combination of JSON objects and an array as a value of a JSON object and POJOs are according to that. Now if there is no record for present and future dates then I'll receive a string instead of an array and that leads to API error java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING. So what I wanna know if there is any way that I can determine - what I'm receiving an array or a string? and how to update POJO according to that to avoid that error.
JSON response when server has no data
{
"Result_Code": "ND",
"Result_Status": "Success",
"Result_Message": "No record found in database.",
"Result_Output": "",
"updatedDate": "20-07-2017 10:44:37"
}
JOSN response will be same when server has data but with one difference
{
"Result_Code": "ND",
"Result_Status": "Success",
"Result_Message": "record found in database.",
"Result_Output": [{multiple elements},
{multiple elements},
{multiple elements}....],
"updatedDate": "20-07-2017 10:44:37"
}
Pojo class named ResponseModel
public class ResponseModel {
private String Result_Code;
private String Result_Status;
private String Result_Message;
private Object Result_Output;
private String updatedDate;
...
}
using Object you can morph as below
call.enqueue(new Callback<ResponseModel>()
{
#Override
public void onResponse(Response<ResponseModel> response, Retrofit retrofit)
{
parseData(); // get other data from ResponseModel Class
if (response.getResultOutput() instanceof List<POJO>)
{
doSomething();
}
else if (response.getResultOutput() instanceof String)
{
doSomething();
}
else //must be error object
{
doSomething();
}
}
#Override
public void onFailure(Throwable t)
{
///Handle failure
}
});
using instanceof you check desired Object type
Where List<POJO> used for multiple elements Model
*check updated solution for parsing ArrayList from response object
hopefully it might be work as you want
catch your json in debug mode and generate pojo class with link below. then compare your class and see difference
http://www.jsonschema2pojo.org/
you can try this method.
try {
callArrayPojo();
} catch (IllegalStateException e) {
callStringPojo();
} catch (Exception e) {
//other}
or you can get ResultMessage generic type
...
private String Result_Code;
private String Result_Status;
private T Result_Message;
...

trying to get results from youtube api via retrofit

get request endpoint method defined in api interface
#GET("youtube/v3/search")
Callback<YoutubeResponse> getYouTubeVideos(#Query("key") String apiKey,
#Query("channelId") String channelId,
#Query("part") String videoPart,
#Query("order") String videoOrder,
#Query("maxResults") int maxResults,
Callback<ChannelListResponse> callback);
Method call to get the results :
Callback <YoutubeResponse> call = apiService.getYouTubeVideos(API_KEY,
"UCjXfkj5iapKHJrhYfAF9ZGg", "snippet", "date", 20, new Callback<ChannelListResponse>() {
#Override
public void onResponse(Call<ChannelListResponse> call, Response<ChannelListResponse> response) {
Log.v("check", response.body().getEtag() + "check");
}
#Override
public void onFailure(Call<ChannelListResponse> call, Throwable t) {
}
}) ;
I am not getting results via this implementaion giving illegal stat exception .
There is some structual mistake because the log says Unable to create call adapter for retrofit2.Callbackfor method ApiInterface.getYouTubeVideos
using these additional links to implement the same . Using this reference link for help : YouTube Data API v3 search JSON response retrofit parsing error
But If keep the return type of getYouTubeVideos() as void. Then it says service method can not have void return type .
A help in this regards will be appreciated
Please correct the retofit syntax like this.
api interface,
#GET("youtube/v3/search")
Call<ChannelListResponse> getYouTubeVideos(#Query("key") String apiKey,
#Query("channelId") String channelId,
#Query("part") String videoPart,
#Query("order") String videoOrder,
#Query("maxResults") int maxResults);
Method call,
Call<ChannelListResponse> call = apiService.getYouTubeVideos(API_KEY,
"UCjXfkj5iapKHJrhYfAF9ZGg", "snippet", "date", 20);
call.enqueue(new Callback<ChannelListResponse>() {
#Override
public void onResponse(Call<ChannelListResponse>call,
Response<ChannelListResponse> response) {
Log.d(TAG, "onResponse");
}
#Override
public void onFailure(Call<ChannelListResponse>call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});

retrofit calling id from url

How I use these query in retrofit network call and display it in category wise result
https://api.themoviedb.org/3/genre/{genre_id}/movies
Perhaps this could help:
interface class
public interface TheApiInterface{
#GET("url/bits/until/{path_variable}/then/more/url")
Call<TheThingResponse> getTheThing(#Path("path_variable") String var);
}
Activity or whatever:
public class ThePlaceYoureCallingItFrom {
//set up the api interface and http client
public TheApiInterface getApi(){
String endpoint = "https://api.root.site/api/";
//set up retrofit object
return new Retrofit.Builder().baseUrl(endpoint)
//add chosen converter factory for pojo serialization
.addConverterFactory(GsonConverterFactory.create())
//add the OKHTTP client
.client(new OkHttpClient.Builder().build())
//now gimme
.build().create(TheApiInterface.class);
}
public void callGetTheThing(){
//create call
Call<TheThingResponse> call = getApi().getTheThing("somePathVar");
//set callback
ThingResponseCallback callback = new ThingResponseCallback(this, THING_RESPONSE_INTENT_FILTER);
//fire
call.enqueue(callback);
}
}
the callback:
public class ThingResponseCallback implements Callback<TheThingResponse>{
#Override
public void onResponse(Call<TheThingResponse> call, Response<TheThingResponse> response) {
if (response.isSuccessful() && response.body() != null) {
Log.i(TAG, "onResponse: success: theResponseFieldIWant1: " + response.theResponseFieldIWant1;);
} else {
Log.i(TAG, "onResponse: something went wrong with the response object " +response.body());
}
}
#Override
public void onFailure(Call<TheThingResponse> call, Throwable t) {
Log.i(TAG, "onFailure: to: " + call.request().url() + " req " + call.request());
}
}
the response pojo:
public class TheThingResponse{
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse1")
public String theResponseFieldIWant1;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse2")
public String theResponseFieldIWant2;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse3")
public String theResponseFieldIWant3;
#SerializedName("theJsonKeyOfTheFieldReturnedInServerResponse4")
public String theResponseFieldIWant4;
}
the JSON you're receiving would look like this:
{
"theJsonKeyOfTheFieldReturnedInServerResponse1": "the value I wanted 1",
"theJsonKeyOfTheFieldReturnedInServerResponse2": "the value I wanted 2",
"theJsonKeyOfTheFieldReturnedInServerResponse3": "the value I wanted 3",
"theJsonKeyOfTheFieldReturnedInServerResponse4": "the value I wanted 4"
}
but you can build more complex POJOs for more complex JSON.
I've found it useful to make my POJOs all share a Serializable parent class, to make them easy to move about in the Callback, but you could also use a ContentProvider in here quite readily and insert some rows into a DB or something like that if you want to have a more permanent storage.
But bear in mind this is all async- if you want synchronous Retrofit calls, you can use call.execute()
At least in the "retrofit" library, it works like this
#GET("/url/{id}")
suspend fun getNews(
#Path("id") searchById:String
):Response<News>

How to handle null param values in Retrofit

We're moving from Apache's http client to Retrofit and we've found some edge cases where param values can be null.
Apache used to intercept these and turn them into empty strings, but Retrofit throws an IllegalArgumentException.
We want to replicate the old behavior so that it doesn't cause any unexpected issues out in production. Is there a way for me to swap these null values with empty strings before ParameterHandler throws an exception?
You can try the following:
My web service (Asp.Net WebAPI):
[Route("api/values/getoptional")]
public IHttpActionResult GetOptional(string id = null)
{
var response = new
{
Code = 200,
Message = id != null ? id : "Response Message"
};
return Ok(response);
}
Android client:
public interface WebAPIService {
...
#GET("/api/values/getoptional")
Call<JsonObject> getOptional(#Query("id") String id);
}
MainActivity.java:
...
Call<JsonObject> jsonObjectCall1 = service.getOptional("240780"); // or service.getOptional(null);
jsonObjectCall1.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
Log.i(LOG_TAG, response.body().toString());
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.e(LOG_TAG, t.toString());
}
});
...
Logcat output:
If using service.getOptional(null);
04-15 13:56:56.173 13484-13484/com.example.asyncretrofit I/AsyncRetrofit: {"Code":200,"Message":"Response Message"}
If using service.getOptional("240780");
04-15 13:57:56.378 13484-13484/com.example.asyncretrofit I/AsyncRetrofit: {"Code":200,"Message":"240780"}

How to stream real time data using Retrofit

I want to observer changes from server in my android app.
So I'm using this interface for open stream with server.
public interface Service {
#GET("/n/{id}/streaming")
void streamThreads(#Path("name_space_id") String Id, #QueryMap Map<String, String> options,#Query("exclude_types") String type, Callback<Object> callback);
}
and this is my method where I can get response in my activity
server.streamThreads(accountInfo.getId(), map, "thread", new Callback<Object>() {
#Override
public void success(Object o, Response response) {
String json = (String) o;
Log.i(TAG,json);
}
#Override
public void failure(RetrofitError error) {
Response r = error.getResponse();
if (r != null)
Log.e(TAG, "error: " + r.getReason());
}
});
So I tested method in web browser and life stream works.
But response comes in my mobile app every 30 minutes. I'm using one activity and call method onCreate().
Thanks
Retrofit provides an #Streaming annotation.
The unread byteStream can then be obtained from the raw OkHttp ResponseBody.

Categories

Resources