How to ignore some variables in models using for retrofit - android

I am using Retrofit to send and receive requests to my server.
I Have a model like below and I have to send it to my server but some variables in this model have not to send to the server.
public class SelectedListModel implements Serializable {
#SerializedName("p_id")
#Expose
private Long pId;
#SerializedName("p_qty")
#Expose
private Double pQty;
#Expose(serialize = false , deserialize = false)
private String pName; //Have not to send to server
#Expose(serialize = false , deserialize = false)
private String pPrice; //Have not to send to server
#Expose(serialize = false , deserialize = false)
private String pImageUrl; //Have not to send to server
}
and because of that, I am getting 400 in my responses from the server.
I used of #Expose(serialize = false, deserialize = false) in order to Ignore variables that have not to send to the server.
But it doesn't work.
Is there any way to do this or I have to create another model just for my server?

Use transient keywork for that
public class SelectedListModel implements Serializable {
#SerializedName("p_id")
#Expose
private Long pId;
#SerializedName("p_qty")
#Expose
private Double pQty;
//#Expose(serialize = false , deserialize = false)
private transient String pName; //Have not to send to server
//#Expose(serialize = false , deserialize = false)
private transient String pPrice; //Have not to send to server
//#Expose(serialize = false , deserialize = false)
private transient String pImageUrl; //Have not to send to server
}
and no need to use #Expose(serialize = false , deserialize = false), into those fields which needed to be excluded.
Read Why does Java have transient fields? and Why use the `transient` keyword in java? for more details.

You can use transient keyword to ignore fields when requesting api calls
JAVA:
transient String name;
KOTLIN:
#Transient
var name: String

change your Retrofit adapter code like this (I hope you're using retrofit2)
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();

Related

Exclude some fields from JSON Body in POST request using Retrofit Android

I am using Retrofit2 to send and receive requests to my server.
Here are my API interface and Model class.
Interface
public interface ApiInterface {
#POST("/users/")
Call<User> signUp(#Body User user);
#POST("/login_url/")
Call<User> login(#Body User user);
}
Retrofit client
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getRestClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
POJO class
public class User {
#SerializedName("id")
private Integer id;
#SerializedName("email")
#Expose
private String email;
#SerializedName("first_name")
private String firstName;
#SerializedName("last_name")
private String lastName;
#SerializedName("password")
#Expose
private String password;
}
I have exposed email and password so that in login request these 2 parameters will be added.
But for another request like Sign up, I required a first name and last name also to be sent along with email and password.
Can I use same "User" class for both ? because if I expose the first name and last name then, those fields will be also sent in login request.
Is there any other way or should I make different POJO classes for both request ?
Instead of sending the whole class , you can use #Field annotation , so your login callback will be something like this :
#FormUrlEncoded
#POST("/login_url/")
Call<User> login(#field("email")String email,#field("password")String password);
#FormUrlEncoded denotes that the request body will use form URL encoding. Fields should be declared as parameters and annotated with #Field.
Can I use same "User" class for both ?
Yes , you can use the same Model as #Body for both requests !
Just make sure where you don't need the required variables just omit them !!
Remove the #SerializedName and #Expose , these are not required and give the variable names according to the json KEYs
public class User {
private Integer id;
private String email;
private String firstName;
private String lastName;
private String password;
}
Edit
Suppose for example , for one request you need :-
4 params you set the model user as
new User(id,email,firstname,lastname); // dont init the password attribute
5 params you set all values to the model like
new User(id,email,firstname,lastname,password);

Retrofit with Moshi - convert JsonArray to String

Below I prepared some of the code I use when I execute query to server.
Response from the server returns list with books in json format. One of the fields params contains list in json array.
How could I force Moshi to treat this field as a raw string?
Here is an explanation of my code.
This is a pseudo-class from where I call instance of Retrofit.
public final class RestApi {
private static final String API_ENDPOINT_KEY = "...";
private final MyApi myApi;
private RestApi() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient client = builder.build();
final Retrofit retrofit = (new Retrofit.Builder())
.baseUrl(API_ENDPOINT_KEY)
.client(client)
.addConverterFactory(MoshiConverterFactory.create())
.build();
myApi = retrofit.create(MyApi.class);
}
public static RestApi getInstance() {
return RestApiGazeta.InstanceHolder.INSTASNCE;
}
private static final class InstanceHolder {
private static final RestApi INSTASNCE = new RestApi();
}
}
This is the Book class with prepared fields for Moshi.
#Generated("com.robohorse.robopojogenerator")
public class Book{
#Json(name = "pages")
private int pages;
#Json(name = "params")
private Params params;
}
This is the query for Retrofit for querying list of books.
#GET("android/getBooks.json")
Call<List<Book>> getBooks(
#Query("section") String section
);
What I have tried was I changed return type in Book class type Params to String but I was returning exception about Expected a string but was BEGIN_ARRAY at path $[0].params.
Okay, so I've read Moshi documentation and it seems to be easy to convert any field to json string. I don't know how to parse it on the fly but here is the solution how to do it after You get ready (in my case) Book object.
Moshi moshi = new Moshi.Builder().build();
JsonAdapter<Params> jsonAdapter = moshi.adapter(Params.class);
String json = jsonAdapter.toJson(body.getParams());
That's it.

How to read Response, different from methods used in pojo class from API in Android

I just want to send back an attribute that was not defined in POJO class.
My POJO class is this
public class PostData {
#SerializedName("Token")
#Expose
private String token;
#SerializedName("Amount")
#Expose
private Integer amount;
#SerializedName("AuthID")
#Expose
private String authID;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amt) {
this.amount = amt;
}
public String getAuthID(){return authID;}
public void setAuthID(String authID){
this.authID = authID;
}
}
Amount,Token,AuthID are sent from the client side to API.Here I used HTTP Cloud function as an HTTP POST.I need to send back the TransID to client side which is not there in POJO class.In client side I need to read the response and store it.
Here is my cloud function code:
exports.Add = functions.https.onRequest((req,res)=>{
//var testPublicKey = [xxxxxxxxxxxxxxxxx]
var stripe = require("stripe")("stripe_key");
console.log("Token:"+req.body.Token)
console.log("Amount:"+req.body.Amount)
var tokenToCharge = req.body.Token;
const amountToCharge = req.body.Amount;
var authID = req.body.AuthID;
const databaseRef = admin.firestore();
const payer = databaseRef.collection('deyaPayUsers').doc(authID).collection('Wallet').doc(authID);
const balance = payer.Usd
stripe.charges.create({
amount : amountToCharge,
currency : "usd",
description : "charge created",
source : tokenToCharge,
}, function(err, charge) {
if(charge.status === "succeeded"){
var trans = databaseRef.runTransaction(t=>{
return t.get(payer)
.then(doc=>{
var updatedBalance = doc.data().Usd + parseInt(charge.amount);
t.update(payer,{Usd : updatedBalance});
});//return close
}).then(result=>{
console.log('Transaction success!');
}).catch(err=>{
console.log('Transaction Failure:',err);
});
}
});
});//end of stripe create charge
you add one field in pojo class using transient key is ignore a value to send api call and get client side value.
transient
private String TransID;
and make getter and setter method.
is there any reason why you do not want to create a variable for the TransID in your POJO class? I understand that your POJO class interacts with your Client Side of your application. Hence, having a variable for the TransID(with getters and Setters) will give you more flexibility to read the response and store it as you want.
To read response using Retrofit have a separate class(which is here PostData) that represents the outputs of the JSON response which we get when a request was served by the backend.create an interface class and with #Method(GET, POST, DELETE etc;) annotation and pass parameters to the method.In client-side pass the parameters to the method and get the response by calling the getmethod of the parameter you are expecting.

Android - How to include a transient field in a serialized object using GSON?

I'm using GSON with Retrofit to send a JSON object in the request body.
I want to include transient fields in serialization, so I called excludeFieldsWithModifiers(Modifier.STATIC), but they're still not included in the JSON request body.
// Retrofit Initialization
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.excludeFieldsWithoutExposeAnnotation();
gsonBuilder.excludeFieldsWithModifiers(Modifier.STATIC);
retrofitBuilder = new Retrofit.Builder();
retrofitBuilder.baseUrl(BASE_URL);
retrofitBuilder.addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()));
Retrofit retrofit = retrofitBuilder.build();
// Field to be serialized
#Expose(deserialize = false, serialize = true)
#SerializedName("Name")
private transient String name;
Use transient keyword
transient public Drawable icon;

GSON Deserializing Array of Custom Objects

I am trying to serialize/deserialize JSON in Android using GSON. I have two classes that look like this:
public class Session {
#SerializedName("name")
private String _name;
#SerializedName("users")
private ArrayList<User> _users = new ArrayList<User>();
}
and:
public class User {
#SerializedName("name")
private String _name;
#SerializedName("role")
private int _role;
}
I am using GSON for serializing/deserializing the data. I serialize like so:
Gson gson = new Gson();
String sessionJson = gson.toJson(session);
This will produce JSON that looks like this:
{
"name":"hi",
"users":
[{"name":"John","role":2}]
}
And I deserialize like so:
Gson gson = new Gson();
Session session = gson.fromJson(jsonString, Session.class);
I'm getting an error when I make this call.
DEBUG/dalvikvm(739): wrong object type: Ljava/util/LinkedList; Ljava/util/ArrayList;
WARN/System.err(739): java.lang.IllegalArgumentException: invalid value for field
I don't know what this error means. I don't see myself doing anything gravely wrong. Any help? Thanks!
Change your code to this:
public class Session {
#SerializedName("name")
private String _name;
#SerializedName("users")
private List<User> _users = new ArrayList<User>();
}
It's a good practice use Interfaces, and GSON requires that (at least, without extra configuration).
Gson converts the array "[ ]" in javascript, to a LinkedList object.
In your code, GSON tries to inject a LinkedList in the _users field, thinking than that field its a List.

Categories

Resources