在对json字符串进行反序列化时,如果没有指定实体类中的泛型类型,那么反序列化出的对象对泛型内容有不同的处理:fastjson将泛型内容反序列化为它自己定义的 com.alibaba.fastjson.JSONObject
;jackson反序列化为 java.util.LinkedHashMap
;gson反序列化为 com.google.gson.internal.LinkedTreeMap
。可见如果不进行泛型指定,反序列化出的对象交给其他的方法或接口使用时会有问题,其实常用的json处理框架对泛型都进行比较好的支持,可以在反序列化时就指定泛型的类型。下面就介绍一下如何使用:
我们需要提前定义好一些实体类。
定义泛型实体,这种实体类常用于接口返回数据:
import java.io.Serializable;
public class ApiResult<T> implements Serializable {
/**
* 响应状态码:200-成功;其他-失败
*/
private int code;
/**
* 响应数据
*/
private T data;
/**
* 响应结果描述
*/
private String message = "";
/**
* 响应耗时:毫秒
*/
private long time;
public ApiResult() {
}
public ApiResult(T data) {
this.data = data;
}
public ApiResult(int code, T data, String message) {
this.code = code;
this.data = data;
this.message = message;
}
public int getCode() {
return code;
}
public ApiResult setCode(int code) {
this.code = code;
return this;
}
public String getMessage() {
return message;
}
public ApiResult setMessage(String message) {
this.message = message;
return this;
}
public T getData() {
return data;
}
public ApiResult setData(T data) {
this.data = data;
return this;
}
public long getTime() {
return this.time;
}
public ApiResult setTime(long time) {
this.time = time;
return this;
}
/**
* 成功
*
* @return
*/
public static ApiResult success() {
ApiResult result = new ApiResult(StatusCode.C_200.getCode(), null, StatusCode.C_200.getMessage());
return result;
}
/**
* 成功
*
* @param data
* @param <T>
* @return
*/
public static <T> ApiResult success(T data) {
ApiResult result = new ApiResult(StatusCode.C_200.getCode(), data, StatusCode.C_200.getMessage());
return result;
}
/**
* 失败
*
* @param statusCode
* @return
*/
public static ApiResult fail(StatusCode statusCode) {
return new ApiResult().setCode(statusCode.getCode()).setMessage(statusCode.getMessage());
}
/**
* 异常
*
* @return
*/
public static ApiResult error() {
return new ApiResult().setCode(StatusCode.C_ERROR.getCode()).setMessage(StatusCode.C_ERROR.getMessage());
}
/**
* 判断响应是否为成功响应
*
* @return
*/
public boolean isSuccess() {
if (this.code != 200) {
return false;
}
return true;
}
public static ApiResult copyCodeAndMessage(ApiResult result) {
return new ApiResult().setCode(result.getCode()).setMessage(result.getMessage());
}
}
定义一个状态枚举信息,将返回的所有状态都在这个枚举中列出:
/**
* 状态枚举
*/
public enum StatusCode {
/**
* 正常
*/
C_200(200, "success"),
/**
* 系统繁忙
*/
C_ERROR(-1, "系统繁忙"),
/**
* 特殊错误信息
*/
C_10000(10000, "特殊错误信息"),
/**
* 用户未登录
*/
C_10001(10001, "用户未登录"),
/**
* 用户无访问权限
*/
C_10002(10002, "用户无访问权限"),
/**
* 用户身份验证失败
*/
C_10003(10003, "用户身份验证失败"),
/**
* 请求参数错误
*/
C_10004(10004, "请求参数错误"),
/**
* 请求信息不存在
*/
C_10005(10005, "请求信息不存在"),
/**
* 更新数据失败
*/
C_10006(10006, "更新数据失败"),
;
private Integer code;
private String message;
StatusCode(int code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public String getMessage() {
return message;
}
public static StatusCode getByCode(int code) {
StatusCode[] values = StatusCode.values();
for (StatusCode value : values) {
if (code == value.code) {
return value;
}
}
return StatusCode.C_ERROR;
}
}
在定义一个类用于表示返回的数据:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DemoVo {
private int id;
private String name;
private String address;
}
以下所有的json反序列化操作都是基于下面的字符串:
{"code":200,"data":{"address":"guangdong-shenzhen-nanshan","id":123,"name":"xingo"},"message":"success","time":0}
- fastjson
fastjson处理泛型比较简单,只需要定义需要泛型处理的com.alibaba.fastjson.TypeReference
就可以,一段代码实现:
ApiResult<DemoVo> api = JSONObject.parseObject(json, new TypeReference<ApiResult<DemoVo>>() {});
也可以先定义一个 java.lang.reflect.Type
,然后再使用这个Type:
Type type = new TypeReference<ApiResult<DemoVo>>() {}.getType();
ApiResult<DemoVo> api = JSONObject.parseObject(json, type);
- jackson
jackson与fastjson类似,可以定义一个com.fasterxml.jackson.core.type.TypeReference
,然后在反序列化时使用它:
ObjectMapper mapper = new ObjectMapper();
// 反序列化的时候如果多了其他属性,不抛出异常
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 如果是空对象的时候,不抛异常
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 指定引用的泛型
TypeReference<ApiResult<DemoVo>> type = new TypeReference<ApiResult<DemoVo>>(){};
ApiResult<DemoVo> api = mapper.readValue(json, type);
或者定义 com.fasterxml.jackson.databind.JavaType
,依次指定主体类class,和多个泛型类class
ObjectMapper mapper = new ObjectMapper();
// 反序列化的时候如果多了其他属性,不抛出异常
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 如果是空对象的时候,不抛异常
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 依次指定主体class,n个泛型class
JavaType javaType = mapper.getTypeFactory().constructParametricType(ApiResult.class, DemoVo.class);
ApiResult<DemoVo> api = mapper.readValue(json, javaType);
- gson
gson处理也是类似的,需要定义一个com.google.gson.reflect.TypeToken
并且在反序列化时使用它:
Type type = new TypeToken<ApiResult<DemoVo>>() {}.getType();
Gson gson = new GsonBuilder().create();
ApiResult<DemoVo> api = gson.fromJson(json, type);
嗯!整体来看,他们在处理泛型时都是大同小异的,在项目中选择合适的框架使用就可以。