我有一个XML
文档,我想反序列化为在编译期间不知道的类的对象,并且类型由文档的根元素名称和{{1} }元素文本内容。问题是双重的:
我的type
文档中有元素列表,因此我无法将其解析为XML
/ JsonNode
,因为在最佳情况下,它只会为我提供列表中的最后一个值,该信息将在此过程中丢失。我发现的所有解决方案都依赖于Map
JsonNode
(例如API
或convertValue
)。
我不能使用treeToValue
-我不知道具体的类将是JsonTypeInfo
,所以我不能使用注释。同样,我不认为deserialised
这样灵活,既可以包含根元素名称又可以包含属性值。
我尝试使用一个自定义反序列化程序,该程序会将实际解析的JsonTypeInfo
包装到另一个JsonNode
中,并且将rootElement作为唯一键(默认情况下,该解析元素不包含此根元素)。之后,我反序列化文档,从节点获取根元素,然后获取type元素值,将两者结合起来,创建类的名称,然后将Object
转换为最终对象。这种方法的问题是,它不能很好地处理列表,并且抛出无效映射并抛出异常,或者根据我编写模型或配置映射器的方式为我提供了列表的最后一个元素。
软件包zm.study.xmlserialize.jackson;
JsonNode
我的方法导致抛出异常:
无法反序列化
import static org.junit.Assert.assertEquals; import java.io.StringReader; import java.util.List; import org.junit.Test; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser; public class JacksonListTest2 { public static class A < D extends AData > { public String type; public D data; } public static class AData {} public static class BRequestData extends AData { @JacksonXmlElementWrapper(useWrapping = false) public List < String > bs; } public static class BRequest extends A {} @Test public void test() throws Exception { String xml; xml = "<Request><type>B</type><data><bs>1</bs><bs>2</bs></data></Request>"; XmlMapper mapper = new XmlMapper(); mapper.registerModule( new SimpleModule() .addDeserializer(JsonNode.class, new JsonNodeDeserializer() { @Override public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws java.io.IOException { String rootName = ((FromXmlParser) p).getStaxReader().getLocalName(); return ctxt.getNodeFactory().objectNode().set(rootName, super.deserialize(p, ctxt)); }; }) ); JsonNode rootNode = mapper.readTree(new StringReader(xml)); String rootName = rootNode.fields().next().getKey(); JsonNode contentNode = rootNode.get(rootName); String type = contentNode.get("type").asText(); String className = getClass().getCanonicalName() + "$" + type + rootName; BRequest value = (BRequest) mapper.convertValue(contentNode, Class.forName(className)); System.out.println(value.data.bs); assertEquals(2, value.data.bs.size()); } }
的实例 VALUE_STRING令牌
我还尝试创建一个自定义反序列化器,仅解析文档中的全部内容以找出我要处理的类型,然后将其余的实际解析(数据元素)委派给默认的反序列化器,但未能成功编写任何明智的代码来做到这一点。
我认为我需要一种新方法,有什么想法吗?