问题
网上很多都是普通的实体类序列化跟反序列化,而对泛型数据的反序列化却比较少,查询了很多资料都不能用,要么就是讲的太复杂,最近在工作中遇到了这个问题,记录下解决方式
资料
首先我们来参考下网上的一段代码,从这段代码中我们可以参看下集合中序列化的方式,但是没有很好的封装,如果写在实际的业务代码中会显得很繁琐,本篇文章我们是借鉴的第一种方式来解决这个问题的
public class Demo{
public String method() throws IOException {
ObjectMapper mapper = new ObjectMapper();
User user = new User();
user.setId(1);
Pager<User> pager = new Pager<User>();
List<User> users = new ArrayList<User>();
users.add(user);
pager.setDatas(users);
String json = mapper.writeValueAsString(pager);
// 方式1
Pager<User> userPager1 = mapper.readValue(json, new TypeReference<Pager<User>>() {
});
// 方式2
Type[] types = new Type[1];
types[0] = User.class;
final ParameterizedTypeImpl type = ParameterizedTypeImpl.make(Pager.class, types, Pager.class.getDeclaringClass());
TypeReference typeReference = new TypeReference<Pager>() {
@Override
public Type getType() {
return type;
}
};
Pager<User> userPager2 = mapper.readValue(json, typeReference);
// 方式3
JavaType javaType = mapper.getTypeFactory().constructParametrizedType(Pager.class, Pager.class, User.class);
Pager<User> userPager3 = mapper.readValue(json, javaType);
// 方式4
JavaType javaType1 = mapper.getTypeFactory().constructParametricType(Pager.class, User.class);
Pager<User> userPager4 = mapper.readValue(json, javaType1);
// 方式5,新建另一个指定具体泛型T的参数的类
PagerAppoint userPager5 = mapper.readValue(json, PagerAppoint.class);
// 数组泛型的序列化和反序列化
String json1 = mapper.writeValueAsString(users);
JavaType javaType2 = mapper.getTypeFactory().constructParametricType(List.class, User.class);
List<User> users1 = mapper.readValue(json1, javaType2);
// HashMap
Map<String, User> map = new HashMap<String, User>(16);
map.put("test", user);
String json2 = mapper.writeValueAsString(map);
// 1
Map<String, User> users2 = mapper.readValue(json2, new TypeReference<Map<String, User>>() {
});
// 2
JavaType javaType3 = mapper.getTypeFactory().constructParametricType(HashMap.class, String.class, User.class);
Map<String, User> users3 = mapper.readValue(json2, javaType3);
return "hello world";
}
}
实体类
创建一个包含泛型的实体类,其中data是一个泛型数据
@Data
public class BaseResponse<T> {
/**
* 请求ID
*/
private String requestId;
/**
* Token验证码
*/
private String queueMsg;
/**
* 错误编码
*/
private String errorCode;
/**
* 数据
*/
private T data;
}
再创建一个data对应的实体类
@Data
public class QuerySubmitErrorInfoResponse {
/**
* 机构名称
*/
private String orgname;
/**
* 支付服务类别
*/
private String bizcatgname;
/**
* 业务类型
*/
private String biztypename;
/**
* 维度名
*/
private String dimname;
/**
* 第二维度名
*/
private String dimnames;
/**
* 校验信息
*/
private String remark;
}
如果此时T data是一个普通的数据对象,比如QuerySubmitErrorInfoResponse这种,此时很好操作,加入是一个List<QuerySubmitErrorInfoResponse> 此时操作变的繁琐
解决
上面所说的,我用的是第一种思路来解决这个问题,需要一个TypeReference来转换,我简单的封装了一下
public <T> T jsonToObject(String responseJson, TypeReference<T> valueTypeRef) {
try {
return mapper.readValue(responseJson, valueTypeRef);
} catch (IOException e) {
throw new JsonUtilException("Failed to convert json to object", e);
}
}
结束
反序列化代码块如下
BaseResponse<List<QuerySubmitErrorInfoResponse >> response = JsonUtil.create().jsonToObject(result, new TypeReference<BaseResponse<List<QuerySubmitErrorInfoResponse >>>() {
});
上传一个我用到的完整的工具类
package net.easipay.util.json;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
public class JsonUtil {
private ObjectMapper mapper = new ObjectMapper();
JsonUtil() {
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
@Override
public void serialize(Object paramT, JsonGenerator paramJsonGenerator,
SerializerProvider paramSerializerProvider) throws IOException {
//设置返回null转为 空字符串""
paramJsonGenerator.writeString("");
}
});
}
public static JsonUtil create() {
return new JsonUtil();
}
public JsonUtil setDateFormat(String pattern) {
mapper.setDateFormat(new SimpleDateFormat(pattern));
return this;
}
public JsonUtil unwrapRootValue() {
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
return this;
}
public JsonUtil wrapRootValue() {
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
return this;
}
public JsonUtil setFilterProvider(FilterProvider filterProvider) {
mapper.setFilterProvider(filterProvider);
return this;
}
public JsonUtil configure(DeserializationFeature feature, boolean state) {
mapper.configure(feature, state);
return this;
}
public JsonUtil setPropertyNamingStrategy(PropertyNamingStrategy propertyNamingStrategy) {
mapper.setPropertyNamingStrategy(propertyNamingStrategy);
return this;
}
public String objectToJson(Object obj) {
try {
return mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new JsonUtilException("Failed to convert object to json", e);
}
}
public <T> T jsonToObject(String responseJson, Class<T> clazz) {
try {
return mapper.readValue(responseJson, clazz);
} catch (IOException e) {
throw new JsonUtilException("Failed to convert json to object", e);
}
}
public <T> T jsonToObject(String responseJson, TypeReference<T> valueTypeRef) {
try {
return mapper.readValue(responseJson, valueTypeRef);
} catch (IOException e) {
throw new JsonUtilException("Failed to convert json to object", e);
}
}
public JsonNode getJsonNode(String jsonStr) {
try {
return mapper.readTree(jsonStr);
} catch (JsonProcessingException e) {
throw new JsonUtilException("Failed to convert request to JsonNode",
e);
} catch (IOException e) {
throw new JsonUtilException("IO exception", e);
}
}
}
至此,完美解决!