Gson parses an exception to an empty string

  • 2020-05-16 06:58:08
  • OfStack

preface

In a real development project, the server would often return an empty value with the empty string "" as the result, but this is problematic in Gson, where if the data type is not a string, Gson parsing would report an error

Json abnormal condition

Let's take a look at one of the background returns, json

Normally json:


{
 "code":0,
 "msg":"ok",
 "data":{
  "id":5638,
  "newsId":5638
 }
}

The entity class corresponding to data part:


public class JsonBean {
 private int id;
 private int newsId;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public int getNewsId() {
  return newsId;
 }

 public void setNewsId(int newsId) {
  this.newsId = newsId;
 }
}

Exception json(background database newsId field did not query the corresponding data):


{
 "code":0,
 "msg":"ok",
 "data":{
  "id":5638,
  "newsId":""
 }
}

So when Gson parses, it throws an exception with a parse error, and app crashes because it cannot convert "" to int

Exception handling for json

We expect that when the json exception is returned in the background, it can also be resolved successfully, and the corresponding null value is converted to the default value, such as: newsId=0;

This excludes the background developer output when you do the correction, or have to rely on their own ah

Let's write a type converter for the int value that needs to implement Gson JsonSerializer<T> The interface and JsonDeserializer<T> The serialization and deserialization interfaces


public class IntegerDefault0Adapter implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
 @Override
 public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
   throws JsonParseException {
  try {
   if (json.getAsString().equals("") || json.getAsString().equals("null")) {// Is defined as int type , If the background comes back "" or null, It returns 0
    return 0;
   }
  } catch (Exception ignore) {
  }
  try {
   return json.getAsInt();
  } catch (NumberFormatException e) {
   throw new JsonSyntaxException(e);
  }
 }

 @Override
 public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) {
  return new JsonPrimitive(src);
 }
}

The same goes for Long and Double types

double= >


public class DoubleDefault0Adapter implements JsonSerializer<Double>, JsonDeserializer<Double> {
 @Override
 public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
  try {
   if (json.getAsString().equals("") || json.getAsString().equals("null")) {// Is defined as double type , If the background comes back "" or null, It returns 0.00
    return 0.00;
  }
   } catch (Exception ignore) {
  }
  try {
   return json.getAsDouble();
  } catch (NumberFormatException e) {
   throw new JsonSyntaxException(e);
  }
 }

 @Override
 public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
  return new JsonPrimitive(src);
 }
}

long= >


public class LongDefault0Adapter implements JsonSerializer<Long>, JsonDeserializer<Long> {
 @Override
 public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
  throws JsonParseException {
  try {
   if (json.getAsString().equals("") || json.getAsString().equals("null")) {// Is defined as long type , If the background comes back "" or null, It returns 0
     return 0l;
    }
   } catch (Exception ignore) {
  }
  try {
   return json.getAsLong();
  } catch (NumberFormatException e) {
   throw new JsonSyntaxException(e);
  }
 }

 @Override
 public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) {
  return new JsonPrimitive(src);
 }
}

So the usage goes like this:


return new Retrofit.Builder()
  .client(okHttpClient)// Set up the network access framework 
  .addConverterFactory(GsonConverterFactory.create(buildGson()))// add json The transformation framework 
  .addCallAdapterFactory(RxJavaCallAdapterFactory.create())// let Retrofit support RxJava
  .baseUrl(baseUrl)
  .build();

/**
 *  Add background return "" and "null" The processing of 
 * 1.int=>0
 * 2.double=>0.00
 * 3.long=>0L
 *
 * @return
 */
public static Gson buildGson() {
 if (gson == null) {
  gson = new GsonBuilder()
    .registerTypeAdapter(Integer.class, new IntegerDefault0Adapter())
    .registerTypeAdapter(int.class, new IntegerDefault0Adapter())
    .registerTypeAdapter(Double.class, new DoubleDefault0Adapter())
    .registerTypeAdapter(double.class, new DoubleDefault0Adapter())
    .registerTypeAdapter(Long.class, new LongDefault0Adapter())
    .registerTypeAdapter(long.class, new LongDefault0Adapter())
    .create();
 }
 return gson;
}

Never crash again when the background json field is empty

conclusion

The above is the whole content of this article, I hope the content of this article can help you in your study or work, if you have any questions, you can leave a message to communicate.


Related articles: