CauCuKien
CauCuKien

Reputation: 1037

Gson can not cast an Object

I call a request network to my server, and server always response a format json look like this format below:

{

   "error": 200,
   "message": "Login Success",
   "message_app": "abcxyz",
   "data": {
     "client_id": "1423423",
     "client_secret": "64646456546"
   }
 } 

Only jsonObject data is include different field for each kind of request. Example for a new response:

{

   "error": 200,
   "message": "Get product success",
   "message_app": "vcxvxcv",
   "data": {
     "product_title": "Product A",
     "product_desc": "This is a description for product A"
   }
 } 

So I decide to make a general class call ServerResult include a field "Object" so that I can cast it to a specific object.

//ServerResult.class

public class ServerResult {
    private int error;
    private String message;
    private String message_app;
    private Object data;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessageApp() {
        return message_app;
    }

    public void setMessageApp(String messageApp) {
        this.message_app = messageApp;
    }

    public int getError() {
        return error;
    }

    public void setError(int error) {
        this.error = error;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getMessage_app() {
        return message_app;
    }

    public void setMessage_app(String message_app) {
        this.message_app = message_app;
    }
}

//Client.java

public class Client {

    private String client_id;
    private String client_secret;

    public String getClientId() {
        return client_id;
    }

    public void setClientId(String client_id) {
        this.client_id = client_id;
    }

    public String getClientSecret() {
        return client_secret;
    }

    public void setClientSecret(String client_secret) {
        this.client_secret = client_secret;
    }
}

After request finished, I convert json to a ServerResult object by GSON:

@Override    
  public void onResponse(String response) {              
     Gson gson = new Gson();
     ServerResult serverResult = gson.fromJson(response, ServerResult.class); //convert json String to ServerResult object

  }

And then cast Data object to a Client object

Client client = (Client)serverResult.getData(); // problem here

Log error from GSON :

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to mypackagename.Client

Is it problem relate with GSON ?

Upvotes: 1

Views: 2564

Answers (3)

Dhaval Patel
Dhaval Patel

Reputation: 10299

When gson parse your json data. There is no way that gson will know that your data field contain client data or product data,as you haven't specified any particular object. So gson will convert that data field into map object.

You can try below approach.

Change your ServerResult as below.

public class ServerResult {
    private int error;
    private String message;
    private String message_app;
    private Map<String, String> data;
}

Now create util method to get Client data from Map.

public static Client getClient(Map<String, String> data){
    Client client = new Client();
    client.setClientId(data.get("client_id"));
    client.setClientSecret(data.get("client_secret"));
    return client;
}

Now use it like..

@Override    
public void onResponse(String response) {              
    Gson gson = new Gson();
    ServerResult serverResult = gson.fromJson(response, ServerResult.class); //convert json String to ServerResult object
    Client client = getClient(serverResult.getData());
}

similarly you can also get product data from same ServerResult object. without creating different parser class.

Upvotes: 0

dev.bmax
dev.bmax

Reputation: 10611

What you can do is to declare the 'data' field to be of type com.google.gson.JsonObject and parse it manually by checking what content there is.

For example:

JsonObject data = serverResult.getData();
if (data.has("client_id")) {
    //parse it as Client
} else {
    //parse it as another type
}

Upvotes: 1

Daniel Veihelmann
Daniel Veihelmann

Reputation: 1487

Unfortunately, it cannot work that way. As you wrote, your data field may come with different contents (i.e. as different classes) depending on the request.

All Gson can see is your object data field in ServerResult. How is Gson supposed to know which exact kind of object (e.g. your Client class) 'hides' within the data object? Gson will not check all available classes from your code and just "try to cast it".

Upvotes: 1

Related Questions