Retrofit / Robospice handle multiple response objects - android

How do I make Retrofit / Robospice handle my api responses in a way that I can get an empty JSON response body like: {}, but also a regular JSON response body?
Currently the empty response body initialises a new POJO, but I only want this to happen if there is actually a filled response body.
I have an object that contains three booleans, and these will always be set to false, while this shouldn't happen.
I somehow have the idea this is caused by my GSON deserializer (I use the default one), but don't know where to start for something like this.
Thanks for any help. :)

Why not using Boolean instead of boolean? That way the default value in null rather than false

Retrofit doesn't touch fields if there's no such fields in json. So init them by yourself.
public class Response {
public boolean value = true;
}

Related

How to make fields optional in Kotlin serialization in using it in retrofit?

I have an API which its response is kind of dynamic. I mean sometimes it return a Jason object with "token" value, and sometimes it returns with "message" value. For handling this scenario I decided to have both field in my data class like below:
data class response {
val message:String;
val token:String;
}
Now I want to make both fields optional in Kotlin serialization. I mean, I want to tell Kotlin serialization that if you couldn't find token in response JSON it's ok to ignore it.
How can I achieve this?
All Kotlin properties with default values are automatically optional.
All I need to do is this:
data class response {
val message:String="";
val token:String="";
}

Parsing API results on Android with Retrofit and Jackson or Gson

I am trying to parse the results of an API call which returns a unique first property.
{
"AlwaysDifferent12345": {
"fixedname1" : "ABC1",
"fixedname2" : "ABC2"
}
}
I am using retrofit2 and jackson/gson and cannot figure out how to cope with dynamic property names within the retrofit2 framework. The following works fine
data class AlwaysDifferentDTO(
#JsonProperty("AlwaysDifferent12345") val alwaysDifferentEntry: AlwaysDifferentEntry
)
I have tried
data class AlwaysDifferentDTO(
#JsonProperty
val response: Map<String, AlwaysDifferentEntry>
)
But this returns errors Can not instantiate value of type... The return value from the API is fixed i.e. map<string, object>.
I have read you can write a deserializer but it looks like I need to deserialize the whole object when all I want to do is just ignore the string associated with the response.
I have read
https://discuss.kotlinlang.org/t/set-dynamic-serializedname-annotation-for-gson-data-class/14758
and several other answers. Given unique properties names are quite common it would be nice to understand how people deal with this when using retrofit2
Thanks
Because the JSON doesn't have a 1-to-1 mapping Jackson can't map it automatically using annotations. You are going to need to make your own Deserializer.
In this tutorial you can learn how to create your own custom Deserializer for Jackson. https://www.baeldung.com/jackson-deserialization
In the tutorial you will see the first line under the deserialize function is
JsonNode node = jp.getCodec().readTree(jp);
using this line you can get the JSON node as a whole and once you have it you can call this function
JsonNode AlwaysDifferent12345Node = node.findParent("fixedname1");
Now that you have that node you can retrieve its value like shown in the rest of the tutorial. Once you have all the values you can return a new instance of the AlwaysDifferentDTO data class.

How to handle such a json properly?

The problem is next.
In response I have JSON like
{
object: {
// a lot of different fields
}
}
I use Retrofit with gson parser. What I really need is just this object. I don't want to create class for response with the only one field. All responses server send in a such manner. As far I understand somewhere I need place simple code for fetching that one object and then use default parser for it.
Probably sorry for stupid question. I used Volley and there was quite a different approach.
Instead of creating a special class to handle this (and another special class for every other server response), just use Map<String, YourRealObjectType>. Then use this method to extract the YourRealObjectType instance for each response:
public static <T> T getFirstValue(Map<String, T> map) {
return map.values().iterator().next();
}
you can convert class into JsonObject class. then cal iterate all the elements in it one by one
#Get
ObservablegetData();
Note : use JsonObject not JSONObject

How to handle non-2XX response codes in RoboSpice?

In my API server returns HTTP 400 response code if request does not pass validation, and provides detailed message, that should be parsed as the response.
For example:
public class RegistrationResponse {
private String emailError; // Detailed message. Null if no error occured
}
But Robospice (Retrofit + OkHttp) fires onRequestFailure() with message "retrofit.RetrofitError: 400 BAD REQUEST" in this case and, of course, does not parse anything.
How should I make it parse the response in case if response code is not 2XX?
You should declare Retrofit methods that return HTTP Response objects and check the raw object in your loadDataFromNetwork() for the status you need. This way, however, you will skip the out-of-the-box functionality of parsing responses and will have to do that manually.
Therefore, you should also find a way to reuse the Converter passed to your RestAdapter in the RetrofitSpiceService. Overriding the RetrofitSpiceService#createConverter() method is probably the simplest way to achieve this.

POST request with Android Annotation REST Service

I am using Android Annotation in my project and trying to send POST request through following code, however there is something wrong in following code as I am not getting response as expected:
#Rest(rootUrl = "http://xyz.com", converters = {GsonHttpMessageConverter.class})
public interface A {
#Post("/authenticate/email/")
public Object attemptLogin(Map data);
}
Where data is (key, value) pair. Is there anything I am missing perhaps Do I have to set request-header or data should not be JSON?
I found the solution from Rest client using Android-Annotations.
Like the GET requests, it is extremely simple to send POST requests using Android-Annotations. One difference is that you need to define the parameters that you are going to send as a custom class (e.g. Event class in the example below) or if you want to control this dynamically, then a Map (e.g. a MultiValueMap). The url for the request can still be constructed in a similar fashion using the variables enclosed inside {...} and the response can be handled similarly as in GET requests.
#Post("/events")
void addEvent(Event event);
#Post("/events/{id}")
void addEventById(Event event, long id);
#Post("/authenticate/event/")
Object authenticateEventData(MultiValueMap data);

Categories

Resources