Java Jackson XML解组和抽象类
我正在尝试使用Jackson 2.4.0Java Jackson XML解组和抽象类,java,xml,jaxb,jackson,Java,Xml,Jaxb,Jackson,我正在尝试使用Jackson 2.4.0XmlMapper解组以下XML: …还有下面的POJO 类根目录{ @JacksonXmlElementWrapper(useWrapping=false) @JsonSubTypes({ @JsonSubTypes.Type(name=“a”,value=POJO_a.class), @JsonSubTypes.Type(name=“b”,value=POJO_b.class) }) public final List objects=new Ar
XmlMapper
解组以下XML:
…还有下面的POJO
类根目录{
@JacksonXmlElementWrapper(useWrapping=false)
@JsonSubTypes({
@JsonSubTypes.Type(name=“a”,value=POJO_a.class),
@JsonSubTypes.Type(name=“b”,value=POJO_b.class)
})
public final List objects=new ArrayList();
}
我还尝试了JAXB@XmlElements
注释,得到了相同的结果,即:
Unrecognized field "a" (class Root), not marked as ignorable (1 known properties: "objects"])
因此,杰克逊似乎认为我的列表被称为“对象”,而不是“a”和“b”。通常我通过使用@JsonProperty(“newName”)
来解决这个问题,但在本例中,我希望由@JsonSubtypes
或@xmlmelements
注释来处理
由于我不能修改输入XML,我还可以用Jackson、Jackson XML或JAXB注释做些什么
更新:忘了说,问题是反序列化到同一个集合(因为我需要保持顺序,它们可以混合)。在不同的领域做这件事很好
“由于我无法修改输入XML,我还可以用Jackson、Jackson XML或JAXB注释做些什么?”
我对Jackson的Xml特性不太熟悉。但通过JAXB和对注释的一点更改,这是可以实现的
查看您的列表
与:
如果为true,则当元素与JAXBContext
已知的标记为xmlanyement
的属性匹配时(例如,有一个具有相同标记名的XmlRootElement的类,或者有一个具有相同标记名的xmlementdecl
),解组器将急切地将该元素解组到JAXB对象,而不是将其解组到DOM
这基本上意味着,如果我们用@XmlRootElement
注释PojoA
和PojoB
,并将元素名作为名称
属性(@XmlRootElement(name=“a”)
)传递,根据定义,这应该是可行的
让我们试一试:
public abstract class AbstractPojo {
// note this class is not annotated. It will be known in the context
// as we're explicitly using the type int the Root class
}
@XmlRootElement(name = "a")
public class PojoA extends AbstractPojo {
}
@XmlRootElement(name = "b")
public class PojoB extends AbstractPojo {
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "root")
public class Root {
@XmlAnyElement(lax = true)
protected List<AbstractPojo> objects;
public List<AbstractPojo> getObjects() {
if (objects == null) {
objects = new ArrayList<>();
}
return this.objects;
}
}
当我尝试peeskillet answer并为JAXB解组器更改Jackson时,使用@xmlements
/@xmlementrefs
成功了(@xmlanyement
由于某种原因没有成功,我得到的是ElementNSImpl
的列表,而不是我自己的类)
与杰克逊合作将是一件好事,但同时,这也是让这件事成功的方法
更新:
我所做的是:
类根目录{
@XmlElements({
@XmlElement(name=“a”,type=PojoA.class),
@XmlElement(name=“b”,type=PojoB.class)
})
public final List objects=new ArrayList();
}
我还向PojoA
添加了@XmlRootElement(name=“a”)
,但我认为当您有@XmlElements
时,不会使用它。这对我不起作用,我得到的是elementsImpl
对象。你知道发生了什么事吗?我将同时添加我的解决方案。请查看我的更新。另外,您是否介意发布您是如何使用@xmlements/@xmlementrefs
实现此功能的。我无法让它工作。是的,这可能在语义上更符合您的域:-)+1
<?xml version="1.0" encoding="UTF-8"?>
<root>
<a/> <b/> <b/> <a/> <a/> <b/> <b/>
</root>
public class JaxbTest {
private static final String FILE_NAME = "test.xml";
public static void main(String[] args) throws Exception {
JAXBContext context = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
File f = new File(FILE_NAME);
Root root = (Root)unmarshaller.unmarshal(f);
List<AbstractPojo> list = root.getObjects();
for (AbstractPojo p : list) {
System.out.print( p instanceof PojoA ? "a " : "b ");
}
System.out.println();
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
JAXBContext.newInstance(Root.class, PojoA.class, PojoB.class);