Gson之TypeAdapter

本文介绍如何使用Gson库解析JSON数据,并通过自定义TypeAdapter处理默认值,确保数据的一致性和避免NullPointerException。适用于前后端数据交互场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    在研发工程中,当我们与服务器进行数据交互的时候,会定义数据格式,而Json是十分常用的格式。而对Json的格式化也是我们常要用到的,一般我会引入第三方框架来帮助我们进行解析工作。如Gson、fastJson、jackson等。

    有时候,由于前后台一些数据格式的不一致或者默认值的不一致,会导致解析失败或者解析出来的数据我们在使用的时候有问题的情况。通常我使用Gson比较多,所以这里解析以Gson来举例如下:

我们的Json:{"result":0,"id":1,"data":"ABC"}

我们的实体类:

public class UserBean {
    public int result;
    public long id;
    public String data;

    @Override
    public String toString() {
        return "result:"+result+" id:"+id+" data:"+data;
    }
}

我们用Gson解析:

Gson gson = new Gson();
Log.e("CALM",jsonStr);
UserBean bean = gson.fromJson(jsonStr,UserBean.class);
Log.e("CALM",bean.data);

这里的jsonStr就是我们上面的json字符串

输出结果如下:

{result:0,id:1,data:"ABC"}
ABC

可以看到这样是没有任何问题的。But,如果我们的json是这样的{"result":0,"id":1,"data":null}就是如果说我们后台的同事对字符串的默认值为null,我们在尝试运行刚才的代码会发现程序崩溃,抛出异常java.lang.NullPointerException: println needs a message,实际在我们打印Log.e("CALM",bean.data); 这句的时候出现的,因为我们输出的null不符合Log的输出规则,它要求的是字符串。实际不光是字符串,如果后台给我们的result默认为null,而我们希望默认为-1怎么办呢?

其实这时候我们可以自定义TypeAdapter来解决。我们先将json字符串改成这样:{"result":null,"id":1,"data":null},而我们希望解析出来result = -1,data = "Empty",默认值可以自己根据实际定义。

首先编写int的adapter 在里面,我们将null的情况赋值为-1

public class IntegerAdapter extends TypeAdapter<Integer> {
    @Override
    public void write(JsonWriter out, Integer value) throws IOException {
        try {
            if(value == null){
                value = -1;
            }
            out.value(value);
        }catch (Exception e){

        }
    }

    @Override
    public Integer read(JsonReader in) throws IOException {
        try {
            Integer value;
            if(in.peek() == JsonToken.NULL) {
                in.nextNull();
                return -1;
            }
            if(in.peek() == JsonToken.BOOLEAN){
                boolean b = in.nextBoolean();
                return b?1:-1;
            }
            if(in.peek() == JsonToken.STRING){
                //这里按自己意愿进行处理
                return 0;
            }else {
                value = in.nextInt();
                return value;
            }
        }catch (Exception e){

        }
        return -1;
    }
}

在编写一个String的adapter 我们将null的情况赋值为了Empty

public class StringAdapter extends TypeAdapter<String> {
    @Override
    public void write(JsonWriter out, String value) throws IOException {
        try {
            if(TextUtils.isEmpty(value)){
                value = "Empty";
            }
            out.value(value);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public String read(JsonReader in) throws IOException {
        try {
            String value;
            if(JsonToken.NULL == in.peek()){
                in.nextNull();
                return "Empty";
            }else {
                return in.nextString();
            }
        }catch (Exception e){

        }
        return "Empty";
    }
}

修改我们创建Gson的代码

Gson gson = new GsonBuilder()
            .registerTypeAdapter(String.class,new StringAdapter())
            .registerTypeAdapter(Integer.class,new IntegerAdapter())
            .registerTypeAdapter(int.class,new IntegerAdapter())
            .create();
//Gson gson = new Gson();
Log.e("CALM",jsonStr);
UserBean bean = gson.fromJson(jsonStr,UserBean.class);
Log.e("CALM",bean.toString());

然后我们调用看下日志

{result:null,id:1,data:null}
result:-1 id:1 data:Empty

可以看到我们解析之后result = -1,data = "Empty"这是符合我们的预期的。

当然对于其余的数据类型,也是可以按自己的实际情况定义之后去处理的,这样我们就定义了统一的结果处理机制了。

`Gson` 是 Google 提供的一个用于 Java 对象序列化和反序列化的库。当你需要自定义类型转换时,可以使用 `TypeAdapter`。对于 `BigDecimal` 类型,你可以创建一个专门处理 `BigDecimal` 的适配器。 首先,你需要创建一个实现了 `TypeAdapter<BigDecimal>` 接口的类,通常这个类会有一个构造函数接收一个 `JsonDeserializer<BigDecimal>` 和一个 `JsonSerializer<BigDecimal>` 来分别解析 JSON 字符串为 `BigDecimal` 和将 `BigDecimal` 序列化为 JSON 字符串: ```java import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import java.io.IOException; import java.math.BigDecimal; public class BigDecimalTypeAdapter extends TypeAdapter<BigDecimal> { private final JsonSerializer<BigDecimal> serializer; private final JsonDeserializer<BigDecimal> deserializer; public BigDecimalTypeAdapter(JsonSerializer<BigDecimal> serializer, JsonDeserializer<BigDecimal> deserializer) { this.serializer = serializer; this.deserializer = deserializer; } @Override public void write(JsonWriter out, BigDecimal value) throws IOException { serializer.serialize(value, out); } @Override public BigDecimal read(JsonReader in) throws IOException { return deserializer.deserialize(in); } } ``` 然后,在使用 `Gson` 进行序列化或反序列化时,你可以注册这个自定义的 `TypeAdapter`: ```java import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapterFactory; public static Gson createCustomizedGson() { TypeAdapterFactory factory = new TypeAdapterFactory() { @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { if (type.getRawType().equals(BigDecimal.class)) { return (TypeAdapter<T>) new BigDecimalTypeAdapter(gson.getAdapter(BigDecimal.class), new BigDecimalJsonDeserializer()); } return null; // 返回默认的 TypeAdapter,如果类型不是 BigDecimal } }; Gson gson = new GsonBuilder() .registerTypeAdapterFactory(factory) .create(); return gson; } // 使用自定义的 BigDecimalTypeAdapter BigDecimal bd = new BigDecimal("123.45"); String json = createCustomizedGson().toJson(bd); // 序列化为 JSON BigDecimal bdFromJson = createCustomizedGson().fromJson(json, BigDecimal.class); // 反序列化从 JSON 到 BigDecimal ``` 这里我们假设你已经有一个 `BigDecimalJsonDeserializer` 类用于解析 JSON 字符串到 `BigDecimal`。记得在实际项目中添加这个类并实现相应的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值