在对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_10003(10002, "用户无访问权限"),/*** 用户身份验证失败*/C_10004(10003, "用户身份验证失败"),/*** 请求参数错误*/C_10002(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);
嗯!整体来看,他们在处理泛型时都是大同小异的,在项目中选择合适的框架使用就可以。