Gson对异常数据的解析类型容错

最近的项目中遇到过 前端的实体中定义的类型,经常与后端对不上

比如字段属性为 float,结果返回 “”;

这种类型对应不上的解析,Gson会抛出错误,整个解析全跪;

目前的需求是想提高解析的容错性,(至少ios在这个方面是第三方框架很好的容错机制)

经过百度后,发现了Gson的健壮性,是可以扩展了。

## 探索1 ##
TypeAdapter

public abstract class TypeAdapter {
    public abstract void write(JsonWriter out, T value) throws IOException;
    public abstract T read(JsonReader in) throws IOException; 
}

通过Gson gson = new GsonBuilder().registerTypeAdapter(XXX.class, new XXXAdapter()) .create();
添加adapter

或者Gson1.0中的【JsonSerializer与JsonDeserializer】

Gson gson = new GsonBuilder()
        .registerTypeAdapter(Integer.class, new JsonDeserializer() {
            @Override
            public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                try {
                    return json.getAsInt();
                } catch (NumberFormatException e) {
                    return -1;
                }
            }
        })
        .create();
JsonSerializer<Number> numberJsonSerializer = new JsonSerializer<Number>() {
    @Override
    public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(String.valueOf(src));
    }
};

—这种方式可以解决的是 以下的解析问题:
System.out.println(gson.toJson(100)); //结果:100
System.out.println(gson.fromJson(“\”\”“, Integer.class)); //结果-1

如果是复杂的实体类型,是无法满足的。

继续

探索2
灵感来源【https://www.jianshu.com/p/c6dd9a6b10ee】

以上连接解决的问题是 null转为”“;

我的需求是 float 遇到“”,可以赋值为默认值 -1;

以下是我的解决方案

public class FloatlNullAdapter extends TypeAdapter<Float> {
    @Override
    public Float read(JsonReader reader) throws IOException {
        // TODO Auto-generated method stub
        if (reader.peek() == JsonToken.STRING) {
            reader.skipValue(); //跳过当前
            return -1f;
        }
        BigDecimal bigDecimal = new BigDecimal(reader.nextString());
        return bigDecimal.floatValue();
    }

    @Override
    public void write(JsonWriter writer, Float value) throws IOException {
        // TODO Auto-generated method stub
        writer.value(value);
    }
}

reader.skipValue(); 是一个关键的地方,当前的value 并不是我们要的类型,继续解析会报错,所以需要跳过去

以上折腾可以满足当前的需求了。
其他类型的容错也是可以自己写,
通过

public class MyTypeAdapterFactory<T> implements TypeAdapterFactory {
    @SuppressWarnings("unchecked")
    public  TypeAdapter create(Gson gson, TypeToken type) {
        Class rawType = (Class) type.getRawType();
        if (rawType == BigDecimal.class) {
            return (TypeAdapter) new BigDecimalNullAdapter();
        } else if (rawType == Float.class || rawType == float.class) {
            return (TypeAdapter) new FloatlNullAdapter();
        }
        return null;
    }
}

上图代码中 if()添加对应的类型+adaoter

测试代码如下

                try {
                    String json = "{\"price\":\"\",\"value\":2.12,\"type\":\"3\"}";
                    Gson gson = new GsonBuilder().registerTypeAdapterFactory(new MyTypeAdapterFactory()).create();
                    price = gson.fromJson(json, Price.class);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (price != null) {
                        Log.d("bsnl", "11");
                    } else {
                        Log.d("bsnl", "22");
                    }
                }
public class Price {
    public float value;
    public float type;
    public float price;

}

修改对应的json中数据达到测试效果
小菜鸟一只,如果有什么理解不对,误人子弟的地方,烦请指出。

你可能感兴趣的:(Android开发)