I am using Retrofit in android and GsonConverterFactory is converter.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://xxxxxxx.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
I want send POST request with body.
public class MasterRequest
{
}
public class User extends MasterRequest
{
#SerializedName("email")
public String email = null;
}
#POST("{path}")
Call<MasterResponse> registerUser(#Path("path") String path, #Body MasterRequest masterRequest);
path is the URL that append with base URL.
When ever I send child class("User") object in parent class reference(MasterRequest), then converter shown empty json; "{}".
But when I send User class object to below registerUser Method, then it working fine.
#POST("{path}")
Call<MasterResponse> registerUser(#Path("path") String path, #Body User user);
How can I send child class object in parent class instance to make request body?
That's how Gson works. The easiest way to serialize polymorphic objects is use RuntimeTypeAdapterFactory. You can find detailed tutorial here. Works great with Retrofit!
Related
While studying Retrofit Library I cae across API Interface I could not understand the Code/terms used inside it. Can anyone explain the lines of code??
public interface ApiInterface {
// For POST request
#FormUrlEncoded // annotation that used with POST type request
#POST("/demo/login.php") // specify the sub url for our base url
public void login(
#Field("user_email") String user_email,
#Field("user_pass") String user_pass, Callback<SignUpResponse> callback);
//user_email and user_pass are the post parameters and SignUpResponse is a POJO class which recieves the response of this API
// for GET request
#GET("/demo/countrylist.php") // specify the sub url for our base url
public void getVideoList(Callback<List<CountryResponse>> callback);
// CountryResponse is a POJO class which receives the response of this API
}
Thanks For any Response!!
Hi is there any simple way to use retrofit with recyclerview to fetch json parser from my online website . So far i used Okhttp to get data from local server.A detailed answered will be really appreciated.Thanks in advance.
This tutorial may definitely help you to load json to listview.
https://www.simplifiedcoding.net/retrofit-android-tutorial-to-get-json-from-server/
For recyclerview, follow this link
https://www.learn2crack.com/2016/02/recyclerview-json-parsing.html
first of all copy the response of your API and create your bean classes through
this site
* By clicking source type to JSON
* Annotation Style to GSON
* Unticking useDoubleNumbers
* Unticking AllowAdition Property
then copy those files to your project
Define your base Url in your Class.
make a interface named ApiController, there declare your API as
#FormUrlEncoded
#POST("your api link excluding the base url")
Call<Bean> callApi(#Field("your parameters") String name);
then in your activity write code
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiController apiController = retrofit.create(ApiController.class);
Call<Bean> result = apiController.callApi("your parameter");
result.enqueue(new Callback<Bean>() {
#Override
public void onResponse(Call<Bean> call, Response<Bean> response) {
}
#Override
public void onFailure(Call<Bean> call, Throwable t) {
}
});
Retrofit 2.0 GET and POST method
The link will gudie to learn the methods of retrofit2.0 for GET and POST method.
http://www.iayon.com/consuming-rest-api-with-retrofit-2-0-in-android/
You can learn retrofit to pass JsonArray and JsonObject in the following link
https://www.androidtutorialpoint.com/networking/retrofit-android-tutorial/
The API I'm working with returns objects (and their containing objects) in a "flat" format and I'm having trouble getting this to work elegantly with Retrofit and RxJava.
Consider this JSON response for an /employees/{id} endpoint:
{
"id": "123",
"id_to_name": {
"123" : "John Doe"
},
"id_to_age": {
"123" : 30
}
}
Using Retrofit and RxJava, how do I deserialize this to a Employee object with fields for name and age?
Ideally I'd like RxJava's onNext method to be called with an Employee object. Is this possible? Could this perhaps be done with some type of custom deserializer subclass (I'm using Gson at the moment)?
I realize I could create an EmployeeResponse object that maps directly to the JSON response, but having to map the EmployeeResponse to the Employee object every time I use this in an activity seems kind of unfortunate. It also gets much more complicated when the flat response also contains other objects that need to get deserialized and set as fields on the Employee.
Is there a better way?
The complete solution to this will seem like a lot, but this will let you write Retrofit interfaces with Employee instead of EmployeeResponse. Here's the game plan:
You will still need both EmployeeResponse and Employee objects, where EmployeeResponse just maps exactly to what you'd get from the API. Treat the response as a builder for Employee and write a static factory method that returns an Employee from an EmployeeResponse, ie. Employee employee = Employee.newInstance(response);
You will be creating a custom TypeAdapterFactory for Gson. When Gson sees you request a Employee object, we will have the TypeAdapter actually create an EmployeeResponse, then return the Employee via the static factory method described above.
Your TypeAdapterFactory will look something like this:
public class EmployeeAdapterFactory implements TypeAdapterFactory {
#Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == Employee.class
? (TypeAdapter<T>) employeeAdapter(gson, (TypeToken<Employee>) type)
: null;
}
private TypeAdapter<Employee> employeeAdapter(Gson gson, TypeToken<Employee> type) {
return new TypeAdapter<Employee>() {
#Override public void write(JsonWriter out, Employee value) throws IOException {
// TODO serialization logic to go from an Employee back to EmployeeResponse structure, if necessary
}
#Override public Employee read(JsonReader in) throws IOException {
return Employee.newInstance(gson.fromJson(in, EmployeeResponse.class));
}
};
}
}
Register the factory when you make Gson:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new EmployeeAdapterFactory())
.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://foo.bar")
.addConverterFactory(GsonConverterFactory.create(gson))
... // your other Retrofit configs, like RxJava call adapter factory
.build();
And now you can safely define all your Retrofit interfaces with Employee instead of EmployeeResponse.
This question already has answers here:
Unable to create call adapter for class example.Simple
(19 answers)
Closed 7 years ago.
I am trying to get response from the following Api :
https://api.github.com/users/username
But I don't know how to get response as String so that I can use the String to parse and get the JSONObject.
Retrofit version used:
retrofit:2.0.0-beta1
I have tried this until now:
public interface GitHubService {
#GET("/users/{user}")
public String listRepos(#Path("user") String user,Callback<String> callback);
}
retrieving :
GitHubService service = retrofit.create(GitHubService.class);
service.listRepos("username", new Callback<String>() {
#Override
public void onResponse(Response response) {
System.out.println(response.toString());
}
#Override
public void onFailure(Throwable t) {
}
});
exception:
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class java.lang.String. Tried:
* retrofit.ExecutorCallAdapterFactory
at retrofit.Utils.resolveCallAdapter(Utils.java:67)
at retrofit.MethodHandler.createCallAdapter(MethodHandler.java:49)
Any help would be really appreciated.
** Update ** A scalars converter has been added to retrofit that allows for a String response with less ceremony than my original answer below.
Example interface --
public interface GitHubService {
#GET("/users/{user}")
Call<String> listRepos(#Path("user") String user);
}
Add the ScalarsConverterFactory to your retrofit builder. Note: If using ScalarsConverterFactory and another factory, add the scalars factory first.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
// add other factories here, if needed.
.build();
You will also need to include the scalars converter in your gradle file --
implementation 'com.squareup.retrofit2:converter-scalars:2.1.0'
--- Original Answer (still works, just more code) ---
I agree with #CommonsWare that it seems a bit odd that you want to intercept the request to process the JSON yourself. Most of the time the POJO has all the data you need, so no need to mess around in JSONObject land. I suspect your specific problem might be better solved using a custom gson TypeAdapter or a retrofit Converter if you need to manipulate the JSON. However, retrofit provides more the just JSON parsing via Gson. It also manages a lot of the other tedious tasks involved in REST requests. Just because you don't want to use one of the features, doesn't mean you have to throw the whole thing out. There are times you just want to get the raw stream, so here is how to do it -
First, if you are using Retrofit 2, you should start using the Call API. Instead of sending an object to convert as the type parameter, use ResponseBody from okhttp --
public interface GitHubService {
#GET("/users/{user}")
Call<ResponseBody> listRepos(#Path("user") String user);
}
then you can create and execute your call --
GitHubService service = retrofit.create(GitHubService.class);
Call<ResponseBody> result = service.listRepos(username);
result.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
e.printStackTrace();
}
});
Note The code above calls string() on the response object, which reads the entire response into a String. If you are passing the body off to something that can ingest streams, you can call charStream() instead. See the ResponseBody docs.
I am using Retrofit to Post form data and recieve back XML. What I have so far works fine but i want to make some changes. Here is my existing code (and it works):
Here is my interface
public interface SignupUser
{
#FormUrlEncoded
#POST("/createaccount.cfm")
SignupServerResponse signup(#Field("e") String email, #Field("p") String password);
}
Here is the code to call the api (again, this works fine, I will explain below what I want to change)
SignUpDetails mDeets; // this gets initialize and set somewhere else
RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint("http://myurl.com")
.setConverter(new SimpleXMLConverter()).build(); // the response is xml, that works fine
SignupUser service = restAdapter.create(SignupUser.class);
SignupServerResponse res = service.signup(mDeets.getE(), mDeets.getP());
How can I make it so that I can pass the SignUpDetails object straight to the signup() method instead of passing in separate Strings? When I change the constructor of signup() to accept SignUpdetails object (see below) and pass my SignUpDetails object in, I get an error saying
No Retrofit Annotation Found
Here is how I would like to define the interface
public interface SignupUser
{
#FormUrlEncoded
#POST("/createaccount.cfm")
SignupServerResponse signup(SignUpDetails deets);
}
And call it like this (instead of passing in all those parameters)
SignupServerResponse res = service.signup(mDeets);
I tried adding #Field above each of my variables in the SignUpDetails class and that doesnt work either (compilation error)
On your interface use #Body annotation for the deets parameter:
#POST("/createaccount.cfm")
SignupServerResponse signup(#Body SignUpDetails deets);
That should convert SignUpDetails into XML (since you use xml converter on your adapter).
It is then your responsibility to parse the XML request body on server.