【发布时间】:2014-10-19 14:42:13
【问题描述】:
假设有一个抽象类 A 具有属性 a 和三个非抽象子类 B、C 和 D。B 没有附加属性,C 包含属性 c,D 包含属性 c 和 d。
我想为抽象类 A 子类化 StdDeserializer 以便能够根据要反序列化的属性的存在来决定选择哪个子类。
我之前从 Codehaus 发布了一些 Jackson 版本,并且使用以下实现可以正常工作:
class AbstractADeserializer extends StdDeserializer<A> {
AbstractADeserializer () {
super(A.class);
}
@Override
public A deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = (ObjectNode) mapper.readTree(jp);
Class<? extends A> requestClass = null;
// root.getFieldNames() is an iterator over all field names
JsonNode cValue = root.findValue("c");
JsonNode dValue = root.findValue("d");
/*
* Check for existence of required fields and choose the
* corresponding request class.
*/
logger.debug(Boolean.toString(c != null));
logger.debug(Boolean.toString(d != null));
if(c != null && d == null) {
logger.debug("Found C");
requestClass = C.class;
} else if(c != null && d != null) {
logger.debug("Found D");
requestClass = D.class;
} else {
logger.debug("Found B");
requestClass = B.class;
}
return mapper.readValue(root, requestClass);
}
}
这工作正常,但在从 FasterXML 迁移到 Jackson 2.4 后,ObjectMapper 不允许 ObjectNode 作为其 readValue 方法的参数。
当我修改要使用的代码时 返回 mapper.readValue(jp, requestClass); 我总是得到
com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
at [Source: org.apache.catalina.connector.CoyoteInputStream@1286ec89; line: 1, column: 559]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3095)
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3009)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1637)
您认为有哪些替代方法可以灵活地确定给定输入的类,而无需手动反序列化对象?对我来说,克隆 JsonParser 以避免耗尽它的输入源看起来很复杂。
【问题讨论】:
-
你好@RobbyCornelissen。谢谢你把我指向这个页面。我知道并且不想包含类型信息属性。
-
我不能自己反序列化对象的另一个原因是我们在其中一个非抽象类中有一个更复杂的嵌套对象。因此手动反序列化会很麻烦,最好委托给 Jackson。
-
我试图对类层次结构做同样的事情(让反序列化器根据字段选择正确的子类),但这种方法不适用于 codehaus 1.9 或 fastxml 2.4.1 .我不断收到 stackoverflow 异常,因为 readValue/treeToValue 调用了反序列化器。解决方法是使用上述技术和 DeserializerModifier - stackoverflow.com/questions/18313323/…。
-
更新:原来我必须将 @JsonDeserialize(using = JsonDeserializer.None.class) 添加到派生类中。这巧妙地避免了递归,一旦我这样做了,我就可以使用上面问题中概述的技术。