6

I use retrofit to implement an interface like this:

Observable<QueryResult> queryData(@Body QueryParams params);

and define the QueryResult class:

class QueryResult {
    int count;
    ...
}

When I execute the queryData statement, it produces the following error:

com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: Invalid double: ""

Apparently, it is caused by the api returning data something like this:

{"count":"",...}

The "count" is designed to represent a number, but somehow or maybe sometimes, the server developer wants to use "" to represent 0.

My question is how do I error handle this situation?

I have tried to do the error handling in the QueryResult class:

class QueryResult {
    String count; // change from int to String;
    ...
    int getCount() {
        // do the error handling
        int ret = 0;
        try {
            ret = Integer.parseInt(count);
        } catch (Exception e) {}
        return ret;
    }
}

But is there a better way of handling it? Declaring the count to be a String seems not quite intuitive. I am supposing there could be an option to configure the retrofit.

Update Thanks for the answers of suggestions for efficiency improvement and registering a TypeAdapter in the gson converter. But what I want to know is if the error handle could be done by the retrofit library itself. The point of view is that when I originally declare the count field as int, it can handle both the integer and string type of value from server, like:

{"count":123,...} or {"count":"123",...}

without error. So I am assuming the error handle could be done together with the integer paring behavior in the library itself.

Thanks in advance.

Pai-Hsiang Huang
  • 342
  • 3
  • 12
  • 1
    See the link below : https://stackoverflow.com/questions/8863429/how-to-handle-a-numberformatexception-with-gson-in-deserialization-a-json-respon – Amir Hossein Mirzaei Apr 13 '18 at 06:10
  • if your response data in count value as string then when you getting data that time convert it. –  Apr 13 '18 at 07:05
  • @RajeshKushvaha Sure, I will ask the backend team for help. I just want to do the error handling so that I won't be waked up in the midnight to check and verify a bug from backend team. Still thanks. – Pai-Hsiang Huang Apr 13 '18 at 08:30
  • @AndroidTeam Yes, this is what I have tried in the QueryResult. I am thinking that if I could still using the count field as int and do the deserialization and error handling together with the retrofit library. – Pai-Hsiang Huang Apr 13 '18 at 08:36
  • @AmirMir According to the link, it seems to be an correct and accepted solution by registering a TypeAdapter and do the error handling in it. However, I will have to write a lot of code to do the error handling. I just want to know if the situation like this can be handled in the retrofit library. – Pai-Hsiang Huang Apr 13 '18 at 08:53

4 Answers4

2

First of all this inconsistent behaviour in API response is not feasible. Retrofit won't be able to handle this situation.You have to manually handle this response as you have mentioned in the question.But you can do that in an efficient way like this

class QueryResult {

        Object count; // change to Object;

        int getCount() {
            // do the error handling
            if (count instanceof Integer) {
                return ((Integer) count);
            } else {
                return 0;
            }
        }
    }
Burhanuddin Rashid
  • 5,260
  • 6
  • 34
  • 51
  • I tried the way you suggest and found that the count object is an instance of String so that the getCount() will always return 0. It seems that the server always returns the count as string type no mater it has value or not. – Pai-Hsiang Huang Apr 13 '18 at 09:05
1

Try to check that your count is empty or not before converting it to it

or better to change the response from backend

Try this

public class QueryResult {

    String count;

    int getCount() {

        try {
            if (!TextUtils.isEmpty(count)) {
                return Integer.parseInt(count);
            }

        } catch (NumberFormatException e) {
        }
        return 0;
    }
}
Goku
  • 9,102
  • 8
  • 50
  • 81
  • This avoids the empty string condition to be thrown. It helps a lot for the efficiency. Thanks. But what I want to know is: Is there a way of doing the error handle by the retrofit library itself? I will edit my port to make it more specific. – Pai-Hsiang Huang Apr 13 '18 at 09:16
1

The sweetest way I can tell you is just parse double as way you do.

Double ans=Double.ParseDouble(yourstringvalue);

This gives ans as double. The problem I get here is that you are receiving an empty string "" Just put the condition on it as

 Double ans=0.0
if(yourstringvalue!="" || yourstringvalue!=null){

  //  then parse here

 ans=Double.ParseDouble(yourstringvalue);


}

You will get required value in ans

Proceed further as

if(ans!=0.0){
//do your task here
}
0

Just use Object instead of primitive datatypes. Instead of int use Integer object. The Integer class wraps a value of the primitive type int in an object. Object classes are available for all primitives datatypes in java

Retrofit return null if value is not found and primitives datatypes (int, double) cannot handle null value and give this error. Object classes of primitive datatypes can handle null values

In your case, this change may solve your issue if this count variable is cause of exception

class QueryResult {
Integer count;
...
}

but your exception say double. I think error is because of some variable which is of double datatype and get null value. Just change primitive double to Double object and It will solve your issue

Double var;
Dharman
  • 30,962
  • 25
  • 85
  • 135