handle retrofit error as a gson model - android

i have a web service for registration. and i have a success response for response code 200 like this
{
"data": {
"email": "azadbar#yahoo.com"
},
"code": 201,
"success": true
}
and i have error response with code 422 like this
{
"message": "The given data was invalid.",
"errors": {
"email": [
"The email has already been taken."
]
}
}
but when also i have problem with password the response error show me like this
{
"message": "The given data was invalid.",
"errors": {
"email": [
"The email must be a valid email address."
],
"password": [
"The password must be at least 6 characters.",
"The password confirmation does not match."
]
}
}
the problem is some field some time show and some time is gone. and also we have some response model and in retrofit interface we should only have One response like RegisterResponse in below sample
#POST("/api/v1/register")
Call<RegisterResponse> register(#Body RegisterRequest request);
how can i handle this response?

You need to create a pojo that means a model class of name RegisterResponse that will have the properties that you are getting in your JSON response. So, according to your example case, it would be like :
Class RegisterResponse{
private Data data;
private String code;
private Boolean success;
private String message;
private Error errors;
}
Class Data{
private String email;
}
Class Error{
private List<String> email;
private List<String> password;
}
Now inside every class, you need to create the getter and setter for every properties that you have included.
So when the response comes then handle it accordingly that mean if it comes null, set the property to null else set the received value for the respective property

You need to make a model with all possible fields and depending on result some will be filled or null.
class Model{
private Data data;
private int code;
private boolean success;
private Errors errors;
private String message;
public isSuccess(){
return success;
}
....
}

Related

Retrofit2 Inconsistency Response from Server in android java

I am new to Android development and learning how to use Retrofit and I am having a hard time to deal with inconsistency response from the server.
There are more than two kinds of responses will be returned from the server.
May I know how to deal with this kind of server response? Should I create different data class to handle it based on the server response?
Server Response
Result - Success
{
"status": true,
"result": {
"id": 1,
"name": "User",
"email": "user#gmail.com"
}
}
Result - Fail
{
"status": false,
"result": []
}
Android Model
public class User implements Serializable {
private boolean status;
private ResultModel result;
public static class ResultModel implements Serializable{
private String id;
private String name;
private String email;
}
}

Getvalue from dynamic keys in Gson

I have one Registration Api which has error object in which it shows Errors Dynamically in Array.
This is the JsonFormat of Api :
{
"status_code": 422,
"status": "error",
"data": {
"errors": {
"password": [
"The password must be between 8 and 15 characters."
],
"mobile_no": [
"The mobile number has already been taken."
]
}
}
}
Here if a user forgot to write name then it will show username array in errors. So it changes dynamically.
My question is how I can set this type of errors in gson.I am using retrofit to call Api.
I did this in my Data class but it showing me errors.
#SerializedName("errors")
#Expose
JsonObject errorObject;
Iterator iterator=new Iterator() {
#Override
public boolean hasNext() {
Iterator keys=errorObject.keys();
if(keys.hasNext()){
}
}
#Override
public Object next() {
return null;
}
}
Please help me how can I getErrors using gson.Thank u
You can use Map to maintin the datastructure like this:
Type type = new TypeToken<Map<String, String>>(){}.getType();
Map<String, String> myMap = gson.fromJson(yourErrorsArrayHere, type);
and then just use myMap.get("your_error_key") to get the particular error.

Retrofit2: Expected BEGIN_ARRAY

I am using for first time of Retrofit2 and I got this error:
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
I know my problem is my pojo class but I can't find the right solution to my problem.I create WCF web service an this service return to me a Arraylist of my user class as a json. this is my jsom response from wcf server by poster:
{
"GetUsersResult": [
{
"CreationDateTime": "/Date(1508174478395)/",
"Id": "8e601956-04ab-4464-9f84-c129141b8198",
"Topic": "Topics",
"UserInfo": {
"Age": "15",
"Email": "",
"LastName": "choopani",
"Name": "niloofar",
"SimId": "89984320001079005854"
},
"UserName": "niloo"
},...
According my response I have created pojo class :
public class User {
#SerializedName("UserInfo")
private ExpChild mChildrenList;
private String UserName, CreationDateTime,Id,Topic;
public User(String mUserName,String mCreationDateTime,String mId,
String mTopic) {
UserName = mUserName;
CreationDateTime = mCreationDateTime;
Id = mId;
Topic = mTopic;
}
this is Interface for my client post method:
#POST("json/GetUsers")
Call<List<User>> getAllUsers();
as you can see, I want to be returned a list of my User.
after that I create retrofit service creator and into my main Activity I've used it:
allUsers.enqueue(new Callback<List<User>>() {
#Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
List<User> users = response.body();
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
Toast.makeText(MainActivity.this, "faild to connect", Toast.LENGTH_SHORT).show();
Log.i("====>", "onFailure: "+ t.getMessage());
}
});
but I got above error!!where is my mistake?
Your server returns a JSON object, but your interface says it expects a JSON array. (The List type).
You need to have a second object to represent the full response by the server:
public class ServerResponse {
#SerializedName("GetUsersResult")
private List<User> users;
... Constructor and getters here
}
Then the Retrofit interface should return Call<ServerResponse> which matches the returned JSON, fixing the error.

How to use parse same json response in android when data is string instead of object?

When i am getting response success class works perfectly. But when it is fail it gave me error.
Response when fail data pass in URL :
{
"success": -1,
"message": "Invalid username or password",
"data": ""
}
Response when correct data pass in URL:
{
"success": 1,
"message": "User successfully logged in",
"data": {
"userId": 219,
"userName": "mp",
"picture": "219.png",
"isBo": false,
"isPo": true,
"isHm": true,
"hmProfileCompletionStatus": 3,
"poProfileCompletionStatus": 2,
"poPhoto": null,
"hmPhoto": null,
"custStripeToken": "xxx",
"accountStripeToken": "xx",
"bgcStatus": true,
"idCardStatus": true,
"isInsured": null,
"amISponsered": false,
"hmRating": null,
"poRating": null,
"email": "xxx#gmail.com"
}
}
UserResponse.java
#Getter
#Setter
public class UserResponse{
private int success;
private String message;
private User data;
}
Error
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 64 path $.data
It is not possible. In your case it should be like this
{
"success": -1,
"message": "Invalid username or password",
"data": {}
}
Ask your backend service team to change it with an empty object so that the same reponse object can be re used
As per your problem statement you need to make generic type for response .Instead of type User for 'data' object in UserResponse.Class make it Object type like this:-
#Getter
#Setter
public class UserResponseCustom{
private int success;
private String message;
private Object data;// modified for any type of data
}
On webservice call,check whether data is instance of User or not, that's it.
Now you can have a check whether it is object or not
if (userResponseCustom.getData() instanceOf User)
/*userResponseCustom is supposed to be object of UserResponseCustom
which you are getting from server*/
{
// it's an object
// do whatever you want with data as User Object
}
else
{
// it is an string, handle it
}

Custom retrofit json deserializer

I've been using Retrofit library recently and I like it so far. However, I've come across API that returns response with the following structure:
"data":
{
"meta":
{
"code": 200
"data": "data"
},
"body": [
{
"id": "id",
"field1": "data",
"field2": "data"
},
{
"id": "id",
"field1": "data",
"field2": "data"
}]
}
Assuming I have following class:
public class Entity {
long id;
String field1;
String field2;
}
and following interface:
public interface EntityService {
#GET("/api/method")
void getEntities(Callback<List<Entity>> callback);
}
what is the correct way to use Retrofit if I want to get a list of Entity objects from data.body element from response? I know I could have passed Response object in the callback and manually parse it using org.json package or something else, but is there any better way?
Why not just make a class that represents the data like you've already half done? That's what I've done in multiple apps along with other developers:
public class Meta {
String code;
String data;
}
public class Data {
Meta meta;
List<Entity> body;
}
public interface EntityService {
#GET("/api/method")
void getEntities(Callback<Data> callback);
}
It seems that extra data in your result could be re-used. You should use a generic class like this one:
public class Data<E> {
Meta meta;
E body;
public static class Meta {
int code;
String data;
}
}
Then you could use
Data<List<Entity>>
or whatever you want:
public interface EntityService {
#GET("/api/method")
void getEntities(Callback<Data<List<Entity>>> callback);
}

Categories

Resources