Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Jackson XML解组和抽象类_Java_Xml_Jaxb_Jackson - Fatal编程技术网

Java Jackson XML解组和抽象类

Java 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

我正在尝试使用Jackson 2.4.0
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);