Jackson - Map<String, Object> 实现的序列化
Jackson - serialization of Map<String, Object> implementation
我关注class:
public class Some implements Map<String, Object>{
private Map<String, Object> innerMap;
//implementation that can only set innerMap in constructor and cannot add or remove values
}
问题是我无法在 jackson 中正确反序列化它。如果我在没有默认输入的情况下进行序列化,那没关系,因为它被序列化为 {"one":"two"} 并正确反序列化(我必须使用
实现反序列化器
return new Some(jp.readValueAs(new TypeReference<HashMap<String,Object>>(){}));
当我打开默认输入时,它被序列化为
["com.class.Some",{"one":"two"}]
但是反序列化抛出
com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.util.HashMap
有什么想法吗?
用 @JsonCreator
:
注释你的构造函数
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
Some some = new Some(new HashMap<String, Object>() {{put("a", 1);}});
String json = mapper.writeValueAsString(some);
System.out.println("serialized : " + json);
some = mapper.readValue(json, Some.class);
System.out.println("deserialized: " + some);
}
// Read only delegating Map
public static class Some extends AbstractMap<String, Object> {
private Map<String, Object> delegate;
@JsonCreator
public Some(Map<String, Object> delegate) {
this.delegate = Collections.unmodifiableMap(delegate);
}
@Override
public Set<Entry<String, Object>> entrySet() {
return delegate.entrySet();
}
}
这就是我需要的 - 自定义解串器:
public class SomeDeserializer extends JsonDeserializer<Some> {
@Override
public Object deserializeWithType(JsonParser jsonParser, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
return typeDeserializer.deserializeTypedFromObject(jsonParser, ctxt);
}
@SuppressWarnings("unchecked")
@Override
public Some deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {
JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(
ctxt.getTypeFactory().constructMapType(Map.class, String.class, Object.class));
return new Some((Map) deserializer.deserialize(jp, ctxt, new HashMap<>()));
}
}
我关注class:
public class Some implements Map<String, Object>{
private Map<String, Object> innerMap;
//implementation that can only set innerMap in constructor and cannot add or remove values
}
问题是我无法在 jackson 中正确反序列化它。如果我在没有默认输入的情况下进行序列化,那没关系,因为它被序列化为 {"one":"two"} 并正确反序列化(我必须使用
实现反序列化器return new Some(jp.readValueAs(new TypeReference<HashMap<String,Object>>(){}));
当我打开默认输入时,它被序列化为
["com.class.Some",{"one":"two"}]
但是反序列化抛出
com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class java.util.HashMap
有什么想法吗?
用 @JsonCreator
:
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
Some some = new Some(new HashMap<String, Object>() {{put("a", 1);}});
String json = mapper.writeValueAsString(some);
System.out.println("serialized : " + json);
some = mapper.readValue(json, Some.class);
System.out.println("deserialized: " + some);
}
// Read only delegating Map
public static class Some extends AbstractMap<String, Object> {
private Map<String, Object> delegate;
@JsonCreator
public Some(Map<String, Object> delegate) {
this.delegate = Collections.unmodifiableMap(delegate);
}
@Override
public Set<Entry<String, Object>> entrySet() {
return delegate.entrySet();
}
}
这就是我需要的 - 自定义解串器:
public class SomeDeserializer extends JsonDeserializer<Some> {
@Override
public Object deserializeWithType(JsonParser jsonParser, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
return typeDeserializer.deserializeTypedFromObject(jsonParser, ctxt);
}
@SuppressWarnings("unchecked")
@Override
public Some deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {
JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(
ctxt.getTypeFactory().constructMapType(Map.class, String.class, Object.class));
return new Some((Map) deserializer.deserialize(jp, ctxt, new HashMap<>()));
}
}