项目中调用第三方接口,返回的接口中包含多种数据类型,因此用反序列化器实现返回数据到具体类型的转换。本文提供三种实现方法(本地均已测试通过)。
Item为返回数据的结构,其中data属性是指不同的返回数据类型,用泛型T表示:
public class Item {
private String name;
private String type;
private T data; //根据type类型,将data反序列化为Data或者Model
}
DataItem和ModelItem实现如下,其中Data和Model是返回数据包含的两种类,这里不作说明:
public class DataItem extends Item{
}
public class ModelItem extends Item{
}
方法一:注解(推荐)
直接在类上加注解
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type" //type类型
)
@JsonSubTypes(
{
@JsonSubTypes.Type(name = "model",value = ModelItem.class), //根据type类型,反序列化到不同类
@JsonSubTypes.Type(name = "data" ,value = DataItem.class)
}
)
public class Item {
private String name;
private String type;
private T data; //根据type类型,将data反序列化为Data或者Model
}
@JsonTypeName("model") //这里对应Item类里type的类型
public class ModelItem extends Item{
}
@JsonTypeName("data") //这里对应Item类里type的类型
public class DataItem extends Item{
}
方法二:反序列化器+注解
定义反序列化器JsonItemDeserializer,同时在Item上加注解
public class JsonItemDeserializer extends JsonDeserializer- {
@Override
public Item deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectCodec codec = p.getCodec();
JsonNode treeNode = codec.readTree(p);
String type = treeNode.get("type").asText();
if ("data".equals(type)){
return codec.treeToValue(treeNode, DataItem.class);
}else if ("model".equals(type)){
return codec.treeToValue(treeNode, ModelItem.class);
}else {
return null;
}
}
}
@JsonDeserialize(using = JsonItemDeserializer.class)
public class Item {
private String name;
private String type;
private T data;
}
方法三:反序列化器+ObjectMapper注册Module
反序列化器JsonItemDeserializer同上
public class JsonItemDeserializer extends JsonDeserializer- {
@Override
public Item deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectCodec codec = p.getCodec();
JsonNode treeNode = codec.readTree(p);
String type = treeNode.get("type").asText();
if ("data".equals(type)){
return codec.treeToValue(treeNode, DataItem.class);
}else if ("model".equals(type)){
return codec.treeToValue(treeNode, ModelItem.class);
}else {
return null;
}
}
}
定义WebConfig类,定义init方法,并添加@PostConstruct注解,在ObjectMapper注册Module
@Configuration
public class WebConfig {
private final ObjectMapper objectMapper;
public WebConfig(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@PostConstruct
public void init(){
// 在ObjectMapper注册Module
SimpleModule module = new SimpleModule();
module.addDeserializer(Item.class, new JsonItemDeserializer());
objectMapper.registerModule(module);
}
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
List> converters = restTemplate.getMessageConverters();
converters.removeIf(httpMessageConverter -> httpMessageConverter instanceof MappingJackson2HttpMessageConverter);
// 删除原json转换,添加注册过的objectMapper
converters.add(new MappingJackson2HttpMessageConverter(objectMapper));
return restTemplate;
}
}
for (Item item : items){
if (item.getData() instanceof Data){
Data data = (Data)item.getData();
}
if (item.getData() instanceof Model){
Model model = (Model)item.getData();
}
}