Gson泛型对象反序列化

在RESTful大行其道的今天。很多服务间的通讯都是采用json格式来进行数据交换的。而java中json解析框架有几个主流的。JacksonJSON-libfastjsonGson。他们各有各的优点。
而Gson我觉是在日常工作中用的较为顺手的一个类库。

通用返回类

public class ResMsg {

    private int code;
    private String msg;
    private T data;

    public ResMsg(){
        code = 0;
        msg = "成功";
    }
    
    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

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

用户实体

public class User extends Object {
    /**
     * 用户id
     */
    private int userId;
    /**
     * 昵称
     */
    private String nickname;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    @Override
    public String toString(){
        return String.format("userId:%d , nickname:%s",userId,nickname);
    }
}

在平时的工作中,序列化和反序列一个是toJson 一个fromJson搞定如下代码

public static void main(String[] args) {
        Gson gson = new Gson();
        User user = new User();
        user.setUserId(1);
        user.setNickname("小书童");
        String jsonData = gson.toJson(user);
        System.out.println(String.format("jsonData:%s",jsonData));
        User newUser = gson.fromJson(jsonData,User.class);
        System.out.println(newUser);
}

输出结果

jsonData:{"userId":1,"nickname":"小书童"}
userId:1 , nickname:小书童

可是当我使用泛型时出现问题了。抛出了类型转换异常
Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.tong467.hellowrold.entity.User
代码如下

public static void main(String[] args) {
        Gson gson = new Gson();
        ResMsg resMsg = new ResMsg<>();
        User user = new User();
        user.setUserId(1);
        user.setNickname("小书童");
        resMsg.setData(user);
        String jsonData = gson.toJson(resMsg);
        System.out.println(String.format("jsonData:%s", jsonData));
        ResMsg newResMsg = gson.fromJson(jsonData, ResMsg.class);
        User newUser = newResMsg.getData();
        System.out.println(newUser);
}

通过异常信息我们可以发现。newResMsg 中Data的数据类型为LinkedTreeMap 也就说Gson在反序列化时并不知道其中泛型的具体数据类型,只能给你反序列化成map了,而这并不是我想要的结果。并且在该状态下的反序列化int会变成double 输出newResMsg.getData().toString() 结果如下

{userId=1.0, nickname=小书童}

这种情况是完全不能接受的,所以需要有个解决的方式。尝试使用fromJson的重载,fromJson(String json, Type typeOfT)。问题得以解决。代码如下

Type type = new TypeToken>(){}.getType();
ResMsg newResMsg = gson.fromJson(jsonData,type);
User newUser = newResMsg.getData();

输出结果

jsonData:{"code":0,"msg":"成功","data":{"userId":1,"nickname":"小书童"}}
userId:1 , nickname:小书童

一切又恢复正常了。
new TypeToken>(){}这个奇怪的写法是因为,TypeToken的构造函数是protected 只有子类才能使用。所以使用匿名内部类来获得Type对象。

你可能感兴趣的:(Gson泛型对象反序列化)