在RESTful大行其道的今天。很多服务间的通讯都是采用json格式来进行数据交换的。而java中json解析框架有几个主流的。Jackson
、JSON-lib
、fastjson
、Gson
。他们各有各的优点。
而Gson我觉是在日常工作中用的较为顺手的一个类库。
通用返回类
public class ResMsg<T> {
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<User> 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<User> 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<ResMsg<User>>(){}.getType();
ResMsg<User> newResMsg = gson.fromJson(jsonData,type);
User newUser = newResMsg.getData();
输出结果
jsonData:{"code":0,"msg":"成功","data":{"userId":1,"nickname":"小书童"}}
userId:1 , nickname:小书童
一切又恢复正常了。
new TypeToken<ResMsg<User>>(){}这个奇怪的写法是因为,TypeToken的构造函数是protected 只有子类才能使用。所以使用匿名内部类来获得Type对象。