I have a very strange problem with Retrofit, in fact it may be a bug of it. I want to send to server a POST request with some data. My data is in a subclass of Request class.
public abstract class Request {}
public abstract class Measurement {}
public class StepMeasurement extends Measurement {
...
public int value;
}
public class SendStepsRequest extends Request {
public List<StepMeasurement> steps;
}
example is of course very simplified. I've prepared an interface for sending it:
public interface EndpointInterface {
@Headers({"Content-Type: application/json"})
@POST("/patients/{id}/{dataType}")
Call<ResponseBody> postRequest(
@Path("id") int patientId,
@Path("dataType") String dataType,
@Header("X-XSRF-TOKEN") String token,
@Header("Cookie") String cookie,
@Body Request req);
}
And I have a retrofit ready to go:
mEndpointInterface = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(getUnsafeOkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.build().create(EndpointInterface.class);
I think that now calling mEndpointInterface.postRequest(1, "steps", "token", "cookie", new SendStepsRequest(5)); should send a JSON looking like that:
{"steps":[{"value":5}]}
However all that is sent is
{}
For me unlogical. I guess that Gson doesn't know how to go down in a class hierarchy, so he doesn't know that SendStepsRequest is a subtype of Request. I've already prepared RuntimeTypeAdapterFactory and it started to work then, but that's strange for me. Shouldn't GSON know about inheritance? So I started to experiment.
And now some interesting stuff. I've created a class RequestWrapper:
public class RequestWrapper {
Request mRequest;
}
and changed my interface to accept RequestWrapper instead of Request and guess what! The result was:
{"mRequest":{"steps":[{"value":5}]}}
so he found out how my classes are hierarchized, but couldn't do it without RequestWrapper.
I've also tried a different thing - I've changed my Interface to accept SendStepsRequest objects and changed List< StepMeasurement > to List< Measurement >. What Retrofit send to the server?
{"steps":[{"value":5}]}
so again, he detected the subtype of Measurement class and used it as he should.
My guess is that there's some bug in Retrofit that prevents proper serialization of objects' of classes passed in interface. What do you think? Maybe I'm doing something wrong?
One more funny thing - same behavior was observed when I've used Jackson instead of Gson.