用于使用Jackson将JSON映射到不同类型映射的ContextualDeserializer
此JSON片段应映射到Java对象,该对象包含用于使用Jackson将JSON映射到不同类型映射的ContextualDeserializer,json,generics,mapping,jackson,Json,Generics,Mapping,Jackson,此JSON片段应映射到Java对象,该对象包含cars类型的Map字段和bikes类型的Map字段。因为自行车和汽车在JSON文件中可以是空字符串,所以我需要一个自定义反序列化器() 我考虑使用一个通用自定义反序列化器的实例,它可以由基于BeanProperty参数的ContextualDeserializer方法的CreateContextent(反序列化配置cfg,BeanProperty属性)返回。通用自定义反序列化程序如下所示: public class MapsGenericDeser
cars
类型的Map
字段和bikes
类型的Map
字段。因为自行车和汽车在JSON文件中可以是空字符串,所以我需要一个自定义反序列化器()
我考虑使用一个通用自定义反序列化器的实例,它可以由基于BeanProperty参数的ContextualDeserializer
方法的CreateContextent(反序列化配置cfg,BeanProperty属性)
返回。通用自定义反序列化程序如下所示:
public class MapsGenericDeserializer<T> extends
JsonDeserializer<Map<String, T>> {
private ObjectMapper mapper; // ObjectMapper without special map deserializer
public MapsGenericDeserializer(ObjectMapper mapper) {
this.mapper = mapper;
}
@Override
public Map<String, T> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectCodec codec = jp.getCodec();
JsonNode node = codec.readTree(jp);
if (!"".equals(node.getTextValue())) {
return mapper.readValue(node,
new TypeReference<Map<String, T>>() {});
}
return null; // Node was an empty string
}
}
公共类MapsGenericDeserializer扩展
JsonDeserializer{
私有对象映射器映射器;//不带特殊映射反序列化器的对象映射器
公共映射通用反序列化器(ObjectMapper映射器){
this.mapper=mapper;
}
@凌驾
公共映射反序列化(JsonParser jp,反序列化上下文ctxt)
抛出IOException、JsonProcessingException{
ObjectCodec codec=jp.getCodec();
JsonNode=codec.readTree(jp);
如果(!“”.equals(node.getTextValue())){
返回mapper.readValue(节点,
新类型引用(){});
}
return null;//节点为空字符串
}
}
下面的上下文序列化程序无法工作,因为无法从MapsGenericDeserializer
转换为JsonDeserializer
。也许这在较新版本的Java中是可能的,但在我编写代码的Android版本中不起作用。那么,我如何实现期望的行为呢
public class MapsDeserializer extends JsonDeserializer<Map<String, ?>>
implements ContextualDeserializer<Map<String, ?>> {
private ObjectMapper mapper;
MapsGenericDeserializer<Car> carDeserializer = new MapsGenericDeserializer<Car>(mapper);
MapsGenericDeserializer<Bike> bikeDeserializer = new MapsGenericDeserializer<Bike>(mapper);
public MapsDeserializer(ObjectMapper mapper) {
this.mapper = mapper;
}
@Override
public JsonDeserializer<Map<String, ?>> createContextual(DeserializationConfig cfg,
BeanProperty property) throws JsonMappingException {
Class<?> targetClass = property.getType().containedType(1).getRawClass();
if(targetClass.equals(Car.class) {
return carDeserializer; // Type mismatch!
} else if (targetClass.equals(Bike.class)) {
return bikeDeserializer; // Type mismatch!
} else {
return this;
}
}
// ...
}
公共类MapsDeserializer扩展JsonDeserializer
实现ContextualDeserializer{
私有对象映射器映射器;
MapsGenericDeserializer CardSerializer=新的MapsGenericDeserializer(映射器);
MapsGenericDeserializer bikeDeserializer=新的MapsGenericDeserializer(映射器);
公共映射序列化程序(ObjectMapper映射器){
this.mapper=mapper;
}
@凌驾
公共JsonDeserializer createContext(反序列化配置cfg,
BeanProperty属性)引发JsonMappingException{
类targetClass=property.getType().containedType(1.getRawClass();
如果(targetClass.equals)等于(Car.class){
return carDeserializer;//类型不匹配!
}else if(targetClass.equals(Bike.class)){
return bikeDeserializer;//类型不匹配!
}否则{
归还这个;
}
}
// ...
}
以下是我可能的方法
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.BeanProperty;
import org.codehaus.jackson.map.ContextualDeserializer;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.module.SimpleModule;
public class Foo
{
public static void main(String[] args) throws Exception
{
EmptyStringAsMapDeserializer<Map<String, ?>> emptyStringAsMapDeserializer =
new EmptyStringAsMapDeserializer<Map<String, ?>>(null, new ObjectMapper());
SimpleModule module = new SimpleModule("ThingsDeserializer", Version.unknownVersion());
module.addDeserializer(Map.class, emptyStringAsMapDeserializer);
ObjectMapper mapper = new ObjectMapper().withModule(module);
Person person = mapper.readValue(new File("input.json"), Person.class);
System.out.println(mapper.writeValueAsString(person));
}
}
class Person
{
public int id;
public String name;
public Map<String, Car> cars;
public Map<String, Bike> bikes;
}
class Car
{
public String color;
public String buying_date;
}
class Bike
{
public String color;
}
class EmptyStringAsMapDeserializer<T>
extends JsonDeserializer<Map<String, ?>>
implements ContextualDeserializer<Map<String, ?>>
{
private Class<?> targetType;
private ObjectMapper mapper;
EmptyStringAsMapDeserializer(Class<?> targetType, ObjectMapper mapper)
{
this.targetType = targetType;
this.mapper = mapper;
}
@Override
public JsonDeserializer<Map<String, ?>> createContextual(DeserializationConfig config, BeanProperty property)
throws JsonMappingException
{
return new EmptyStringAsMapDeserializer<Object>(property.getType().containedType(1).getRawClass(), mapper);
}
@Override
public Map<String, ?> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
JsonNode node = jp.readValueAsTree();
if ("".equals(node.getTextValue()))
return new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(node, mapper.getTypeFactory().constructMapType(Map.class, String.class, targetType));
}
}
导入java.io.File;
导入java.io.IOException;
导入java.util.HashMap;
导入java.util.Map;
导入org.codehaus.jackson.JsonNode;
导入org.codehaus.jackson.JsonParser;
导入org.codehaus.jackson.JsonProcessingException;
导入org.codehaus.jackson.Version;
导入org.codehaus.jackson.map.BeanProperty;
导入org.codehaus.jackson.map.ContextualDeserializer;
导入org.codehaus.jackson.map.DeserializationConfig;
导入org.codehaus.jackson.map.DeserializationContext;
导入org.codehaus.jackson.map.jsonderializer;
导入org.codehaus.jackson.map.JsonMappingException;
导入org.codehaus.jackson.map.ObjectMapper;
导入org.codehaus.jackson.map.module.SimpleModule;
公开课Foo
{
公共静态void main(字符串[]args)引发异常
{
EmptyStringAsMapDeserializer EmptyStringAsMapDeserializer=
新的EmptyStringAsMapDeserializer(null,新的ObjectMapper());
SimpleModule=new SimpleModule(“ThingsDeserializer”,Version.unknownVersion());
module.addDeserializer(Map.class,emptyStringAsMapDeserializer);
ObjectMapper mapper=new ObjectMapper().withModule(模块);
Person=mapper.readValue(新文件(“input.json”)、Person.class);
System.out.println(mapper.writeValueAsString(person));
}
}
班主任
{
公共int id;
公共字符串名称;
公共地图车;
公共地图自行车;
}
班车
{
公共字符串颜色;
公开字符串购买日期;
}
职业自行车
{
公共字符串颜色;
}
类EmptyStringAsMapDeserializer
扩展JsonDeserializer
实现ContextualDeserializer
{
私有类targetType;
私有对象映射器映射器;
EmptyStringAsMapDeserializer(类targetType,对象映射器映射器)
{
this.targetType=targetType;
this.mapper=mapper;
}
@凌驾
公共JsonDeserializer createContext(反序列化配置,BeanProperty属性)
抛出JsonMappingException
{
返回新的EmptyStringAsMapDeserializer(属性.getType().containedType(1).getRawClass(),映射器);
}
@凌驾
公共映射反序列化(JsonParser jp,反序列化上下文ctxt)
抛出IOException、JsonProcessingException
{
JsonNode=jp.readValueAsTree();
如果(“.equals(node.getTextValue()))
返回新的HashMap();
ObjectMapper mapper=新的ObjectMapper();
返回mapper.readValue(节点,mapper.getTypeFactory().constructMapType(Map.class,String.class,targetType));
}
}
泛型类型参数可能有点乱。我做了一点快速复制粘贴。我如何使用这样一个带注释的反序列化程序?
@JsonDeserializer(?)public void setBikes(List bikes)
我建议发布一个新问题。抱歉,我单独添加了我的问题:,
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.BeanProperty;
import org.codehaus.jackson.map.ContextualDeserializer;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.module.SimpleModule;
public class Foo
{
public static void main(String[] args) throws Exception
{
EmptyStringAsMapDeserializer<Map<String, ?>> emptyStringAsMapDeserializer =
new EmptyStringAsMapDeserializer<Map<String, ?>>(null, new ObjectMapper());
SimpleModule module = new SimpleModule("ThingsDeserializer", Version.unknownVersion());
module.addDeserializer(Map.class, emptyStringAsMapDeserializer);
ObjectMapper mapper = new ObjectMapper().withModule(module);
Person person = mapper.readValue(new File("input.json"), Person.class);
System.out.println(mapper.writeValueAsString(person));
}
}
class Person
{
public int id;
public String name;
public Map<String, Car> cars;
public Map<String, Bike> bikes;
}
class Car
{
public String color;
public String buying_date;
}
class Bike
{
public String color;
}
class EmptyStringAsMapDeserializer<T>
extends JsonDeserializer<Map<String, ?>>
implements ContextualDeserializer<Map<String, ?>>
{
private Class<?> targetType;
private ObjectMapper mapper;
EmptyStringAsMapDeserializer(Class<?> targetType, ObjectMapper mapper)
{
this.targetType = targetType;
this.mapper = mapper;
}
@Override
public JsonDeserializer<Map<String, ?>> createContextual(DeserializationConfig config, BeanProperty property)
throws JsonMappingException
{
return new EmptyStringAsMapDeserializer<Object>(property.getType().containedType(1).getRawClass(), mapper);
}
@Override
public Map<String, ?> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
JsonNode node = jp.readValueAsTree();
if ("".equals(node.getTextValue()))
return new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(node, mapper.getTypeFactory().constructMapType(Map.class, String.class, targetType));
}
}