Retrofit POST with a json object containing parameters - android

I'm using Retrofit to send a POST request to my server:
#POST("/login")
void login( #Body User user ,Callback<User> callback);
Where my user object has only email and password fields.
Checking the logs, I can see that my parameters are sent with this format:
D/Retrofit﹕{"email":"example#test.com","password":"asdfasdf"}
What I need to do to my parameters be sent like this?
{"user" : {"email":"example#test.com","password":"asdfasdf"} }

EDIT: Making the right way, using a custom JsonSerializer:
public class CustomGsonAdapter {
public static class UserAdapter implements JsonSerializer<User> {
public JsonElement serialize(User user, Type typeOfSrc,
JsonSerializationContext context) {
Gson gson = new Gson();
JsonElement je = gson.toJsonTree(user);
JsonObject jo = new JsonObject();
jo.add("user", je);
return jo;
}
}
}
And then, on your API Client builder:
public static RestApiClient buildApiService() {
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(User.class, new CustomGsonAdapter.UserAdapter())
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL)
.setConverter(new GsonConverter(gson))
.build();
return restAdapter.create(MudamosApi.class);
}

The simplest mode to solve your problem is creating a RequestPOJO class, for example:
File User.java:
public class User{
public String email;
public String password;
}
File LoginRequestPojo.java:
public class LoginRequestPojo{
public User user;
public LoginRequestPojo(User user){
this.user = user;
}
}
And, in your retrofit 2 request:
#POST("/login")
void login( #Body LoginRequestPojo requestPojo, Callback<User> callback);
Finally, your request body:
{"user":{"email":"someone#something.com","password":"123123"}}

Related

retrofit request body is adding double quotes in #Body parameter

I am trying to serialize the request before sending it to the retrofit for webservice calls.
as i am serializing the request , i need to pass json string to retrofit calls in #Body paramenter and due to that
the generated json string results into following json string with the " (Double quotes in front and end ).
"{\"access_token\":\"d80fa6bd6f78cc704104d61146c599bc94b82ca225349ee68762fc6c70d2dcf0\",\"fitness\":[{\"_id\":\"1d051bfe-df30-4fa0-808b-9d7300a608ab\",\"activity_id\":\"877284d3-4f36-4ec0-a536-11563207dc4d\",\"calories\":600.0,\"distance\":40.0,\"intensity\":\"100\",\"timestamp\":\"2018-07-18T12:56:43+00:00\",\"type\":\"Running\",\"utc_offset\":\"+05:30\"},{\"_id\":\"2004ff72-707d-489a-927e-4cdeed410095\",\"activity_id\":\"5ed7c90f-805e-4763-aa62-7f8126c84f06\",\"calories\":600.0,\"distance\":40.0,\"intensity\":\"100\",\"timestamp\":\"2018-07-18T12:56:43+00:00\",\"type\":\"Running\",\"utc_offset\":\"+05:30\"}]}"
as there are double quotes the third party api is unable to parse it successfully.
here is my reqeust serializer code
public class RequestSerializer implements JsonSerializer<Request<?>> {
#Override
public JsonElement serialize(Request<?> request, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new GsonBuilder().create().toJsonTree(request,Request.class).getAsJsonObject();
JsonElement requestList = jsonObject.get("requestList");
jsonObject.remove("requestList");
jsonObject.add("fitness",requestList);
return jsonObject;
}
}
code to call retrofit webservice
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithoutExposeAnnotation();
builder.registerTypeAdapter(Request.class, new RequestSerializer());
Gson gson = builder.create();
String data = gson.toJson(request);
Flowable<Response> fitnessFlowable = new WebRequest().getRemoteClient().create(FitnessApi.class).postFitnessData("5b238abb4d3590001d9b94a8",data);
Using objects eliminates string quoting request in POST #Body,
example as my working code:
class Data{
#SerializedName("access_token")
#Expose
private String access_token;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
// Other field defined here
}
#Keep
class Result{
#SerializedName("rc") int rc;
}
#Keep
interface APIFitness{
#Headers("Content-Type: application/json")
#POST("api/save/")
Observable<Result> Save(#Body Data data);
//More methods..
}
using
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("url")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
APIFitness service = retrofit.create(APIFitness.class);
Data data = new Data();
authCode.setAccess_token(token);
service.Save(data)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.subscribe( data -> { } )

Get OAuth Token from Web API to android

I'm trying to get ِِOAuth token in android from my web api. I have tested the api in Postman and it's working perfect.
Screenshot for the successful call from Postman
now I need to call this Api from my android app using retrofit 2 to get the token, for that I tried to use the following interface but it's not working.
#FormUrlEncoded
#POST("/Token")
public Call<String> Token(#Field("grant_type") String grant_type, #Field("username") String username, #Field("password") String password);
How can I get this done?
In my case I using this below way to call Web Api in Android Application.
Note : I am using OkHttp library.
Create Token class
public class Token {
public String access_token;
public String token_type;
public int expires_in;
public Token(){
}
}
Now add OkHttp library jar to your Project.
for more detail visit this :
http://square.github.io/okhttp/
Now to get OAuth Token call this way
OkHttpClient client = new OkHttpClient();
Request.Builder builder = new Request.Builder();
builder.url(write your url here);
builder.addHeader("Content-Type", "application/x-www-form-urlencoded");
builder.addHeader("Accept", "application/json");
FormEncodingBuilder parameters = new FormEncodingBuilder();
parameters.add("grant_type", "password");
parameters.add("username", edituser);
parameters.add("password", editpassword);
builder.post(parameters.build());
try {
Response response = client.newCall(builder.build()).execute();
if (response.isSuccessful()) {
String json = response.body().string();
}
catch(Exception e){
// catch Exception here
}
finally in response you will get your Token.
Late but it might help someone
Interface class
#FormUrlEncoded
#POST("/Token")
void getTokenAccess(#Field("grant_type") String grantType, #Field("username") String username, #Field("password") String password, Callback<TokenResponse> callback);
TokenResponse class
public class TokenResponse {
private String access_token,token_type,expires_in,userName;
public String getAccess_token() {
return access_token;
}
public String getToken_type() {
return token_type;
}
public String getExpires_in() {
return expires_in;
}
public String getUserName() {
return userName;
}
}
I am using retrofit 1.9.0
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT_URL).setLogLevel(RestAdapter.LogLevel.FULL)
.build();
NetApi api = adapter.create(NetApi.class);
api.getTokenAccess("password", email, password, new Callback<TokenResponse>() {
#Override
public void success(TokenResponse tokenResponse, Response response) {
showProgress(false);
try{
MainActivity.tokenResponse = tokenResponse;
startActivity(new Intent(LoginActivity.this, MainActivity.class));
}catch (Exception e){
Toast.makeText(LoginActivity.this,"Unknown Error",Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(LoginActivity.this,""+error.getMessage(),Toast.LENGTH_LONG).show();
showProgress(false);
}
});

How to read response after Posting data to server using Retrofit v2 library

I am working on Retrofit v2 library for network calls.I am using following dependencies in build.gradle file.
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
1.User.java
public class User {
#SerializedName("email")
String email;
#SerializedName("password")
String password;
public User(String email, String password) {
this.email = email;
this.password = password;
}
}
2.MyAPI.java
public interface MyAPI {
#GET("{roomID}")
Call<List<Message>>loadMessages(#Path("roomID") String roomID);
#POST("almabay_oauth/authorize")
Call<User>login(#Body User user);
}
3.MainActivity.java
public class MainActivity extends AppCompatActivity {
String roomID = "548b737c0eadfb00eb93891bb28242e5";
MyAdapter adapter;
ListView lv;
List<Message> items;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.lv);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://pms.vebific.com:81/chat/index/")
.addConverterFactory(GsonConverterFactory.create())
.build();
MyAPI myAPI = retrofit.create(MyAPI.class);
Call<List<Message>> call = myAPI.loadMessages(roomID);
call.enqueue(new Callback<List<Message>>() {
#Override
public void onResponse(Response<List<Message>> response, Retrofit retrofit) {
// Log.e("ResponseP", String.valueOf(response.body()));
List<Message> items = response.body();
Iterator iterator = items.iterator();
while (iterator.hasNext()) {
Message message = (Message) iterator.next();
String user = message.getUser();
//Log.e("User", user);
}
int statusCode = response.code();
//Log.e("StatusCode", String.valueOf(statusCode));
adapter = new MyAdapter(getApplicationContext(), items);
lv.setAdapter(adapter);
}
#Override
public void onFailure(Throwable t) {
}
});
//--------------POST-------------
Retrofit retrofit1 = new Retrofit.Builder()
.baseUrl("http://phpstack-11819-25991-62288.cloudwaysapps.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
MyAPI myPostApi = retrofit1.create(MyAPI.class);
User user = new User("j#yahoo.com", "Admin123#");
Call<User> call1 = myPostApi.login(user);
call1.enqueue(new Callback<User>() {
#Override
public void onResponse(Response<User> response, Retrofit retrofit) {
Log.e("Response code ", String.valueOf(response.code()));
User user1 = response.body();
Log.e("Response Message",response.message());
}
#Override
public void onFailure(Throwable t) {
}
});
}
}
I have succesfully handled GET request method using this library but i am not able to understand how to read the response after posting data to server using this library.Here i am sending email ID and password to server using Retrofit library.I am getting the status code as 200 here.It means everything is working fine.I know after posting data to server successfully,i am getting some response string .But here i am unable to view the response.Please help.
as you said you got response code 200 it means there is no issue with your request and response.
use OkHttpLoggingIntercepter class.
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient = new OkHttpClient();
httpClient.interceptors().add(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constant.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient)
.build();
you will get detailed log of your response and all the errors if any.
one more thing Gson Converter only parse json data which has json object at root. not JsonArray.
so check your response string as well in log by writing above code.
try to send this POST request via Postman plugin for Chrome, maybe your User class is wrong

Extracting JSON data with Retrofit and Gson

I'm trying to figure out how to extract data from my JSON response and loop through the data. I have the following Retrofit code to request the JSON data from my REST API:
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(URL)
.build();
final ApiEndpointInterface apiService = restAdapter.create(ApiEndpointInterface.class);
apiService.getJsonData(1, new Callback<User>() {
#Override
public void success(User user, Response response) {
Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new Deserializer()).create();
User c = gson.fromJson(response.getBody().toString(), User.class);
}
#Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace();
}
});
And my deserializer:
class Deserializer implements JsonDeserializer<User> {
#Override
public User deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException {
// Get the "content" element from the parsed JSON
JsonElement content = je.getAsJsonObject().get("data");
// Deserialize it. You use a new instance of Gson to avoid infinite recursion
// to this deserializer
return new Gson().fromJson(content, User.class);
}
}
The JSON response:
{
"success":true,
"data":[
{
"id":"1",
"username":"User1"
},
{
"id":"2",
"username":"User2"
}
]
}
Within Retrofit's success callback, I'm not sure how to actually loop through the data's items and extract the data from it (like the person's username).
Create this model classes:
private class ResponseData {
public boolean success;
public List<User> data;
}
private class User {
public String id;
public String username;
}
Now you can do this:
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(URL)
.build();
final ApiEndpointInterface apiService = restAdapter.create(ApiEndpointInterface.class);
apiService.getJsonData(1, new Callback<ResponseData>() {
#Override
public void success(ResponseData responseData, Response response) {
for (User u : responseData.data) {
String name = u.username;
// etc
}
}
#Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace();
}
});

Getting simple JSON object response using Retrofit library

I have a web query with JSON response as:
{
"status":true,
"result":
{
"id":"1",
"name":"ABC 1",
"email":"info#ABc.dcom",
"password":"123456",
"status":false,
"created":"0000-00-00 00:00:00"
},
"message":"Login successfully"
}
I am using the following code for:
#GET("/stockers/login")
public void login(
#Query("email") String email,
#Query("password") String password,
Callback<JSONObject> callback);
In Debugger the query made by the Retrofit library is correct, however I get an empty JSON in response.
ApiManager.getInstance().mUrlManager.login(
email.getText().toString().trim(),
password.getText().toString().trim(),
new Callback<JSONObject>()
{
#Override
public void success(JSONObject jsonObj, Response response)
{
mDialog.dismiss();
Simply use JsonElement insted of JSONobject. Like:
#GET("/stockers/login")
Call<JsonElement> getLogin(
#Query("email") String email,
#Query("password") String password
);
The answers seam kinda old and for Retrofit 1, if you are using Retrofit 2 and don't want to use a converter you have to use ResponseBody.
#GET("/stockers/login")
public void login(
#Query("email") String email,
#Query("password") String password,
Callback<ResponseBody> callback);
And then in your callback in the onResponse method call string on the body and create a JSONObject from it.
if(response.isSuccessful())
JSONObject json = new JSONObject(response.body().string());
Instead of Callback with JSONObject class, you could use the Retrofit basic callback which use the Response class and then, once you get the response, you had to create the JSONObject from it.
See this:
https://stackoverflow.com/a/30870326/2037304
Otherwise you can create your own model class to handle the response.
First the Result class:
public class Result {
public int id;
public String name;
public String email;
public String password;
public boolean status;
public Date created;
}
And then your response class to use with Retrofit
public class MyResponse {
public boolean status;
public Result result;
public String message;
}
Now you can call:
#GET("/stockers/login")
public void login(
#Query("email") String email,
#Query("password") String password,
Callback<MyResponse> callback);
You can create custom factory like belowe or copy it from here :
https://github.com/marcinOz/Retrofit2JSONConverterFactory
public class JSONConverterFactory extends Converter.Factory {
public static JSONConverterFactory create() {
return new JSONConverterFactory();
}
private JSONConverterFactory() {
}
#Override public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (type == JSONObject.class
|| type == JSONArray.class) {
return JSONRequestBodyConverter.INSTANCE;
}
return null;
}
#Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
if (type == JSONObject.class) {
return JSONResponseBodyConverters.JSONObjectResponseBodyConverter.INSTANCE;
}
if (type == JSONArray.class) {
return JSONResponseBodyConverters.JSONArrayResponseBodyConverter.INSTANCE;
}
return null;
}
}
public class JSONRequestBodyConverter<T> implements Converter<T, RequestBody> {
static final JSONRequestBodyConverter<Object> INSTANCE = new JSONRequestBodyConverter<>();
private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain; charset=UTF-8");
private JSONRequestBodyConverter() {
}
#Override public RequestBody convert(T value) throws IOException {
return RequestBody.create(MEDIA_TYPE, String.valueOf(value));
}
}
public class JSONResponseBodyConverters {
private JSONResponseBodyConverters() {}
static final class JSONObjectResponseBodyConverter implements Converter<ResponseBody, JSONObject> {
static final JSONObjectResponseBodyConverter INSTANCE = new JSONObjectResponseBodyConverter();
#Override public JSONObject convert(ResponseBody value) throws IOException {
try {
return new JSONObject(value.string());
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
static final class JSONArrayResponseBodyConverter implements Converter<ResponseBody, JSONArray> {
static final JSONArrayResponseBodyConverter INSTANCE = new JSONArrayResponseBodyConverter();
#Override public JSONArray convert(ResponseBody value) throws IOException {
try {
return new JSONArray(value.string());
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
}
try this instead :
#GET("/stockers/login")
public void login(
#Query("email") String email,
#Query("password") String password,
Callback<Response> callback); // set the callback generic parameter to Response
ApiManager.getInstance().mUrlManager.login(
email.getText().toString().trim(),
password.getText().toString().trim(),
new Callback<Response>()
{
#Override
public void success(Response response, Response response1)
{
String json = response.getBody();
try {
JSONObject jsonObj = new JSONObject(json);
} catch(JSONException e) {
}
alog.dismiss();
Just define the type of the object you want to get as a String as com.google.gson.JsonObject instead of String and call .toString() on that object to get the JSON string itself.
I`m using this site to create my classes (POJO) from JSON.
http://www.jsonschema2pojo.org/
just be sure to set to JSON insted of JSON Schema and check GSON, because retrofit is using GSON as well for parsing.
your retrofit code looks fine.
Use JacksonConverterFactory instead of GsonConverterFactory while setting up Retrofit. Now you can directly work with JsonObject responses.
compile 'com.squareup.retrofit2:converter-jackson:2.1.0'

Categories

Resources