JAXB/Jackson: Sequence of two elements without parent tag

。_饼干妹妹 提交于 2019-12-11 09:47:04

问题


Update: Looking for a Jackson or JAXB solution.

After researching a bit about behavior of Jackson, I found that Jackson will always use a wrapper for collections. So probably what I need is not possible to do with Jackson. Hence, added JAXB to title.


Original Question

I need to create POJO for following XML pattern.

<ABWrap>
    <A></A>
    <B></B>
    <A></A>
    <B></B>
    ...
    ... n times
</ABWrap>

I've tried following POJOs. But these are not generating desired result.

class AB {
    @JacksonXmlProperty(localName = "A")
    private String A;
    @JacksonXmlProperty(localName = "B")
    private String B;
}

@JacksonXmlRootElement(localName = "ABWrap")
class ABWrap {
    @JacksonXmlElementWrapper(useWrapping = false)
    private AB[] ab = new AB[n];
}

I need to maintain the condition that pair of <A></A> and <B></B> should come together. Sequence of elements is important.
Following pattern will not work in my case:

<ABWrap>
    <A></A>
    <A></A>
    ...
    ... n times
    <B></B>
    <B></B>
    ...
    ... n times
</ABWrap>

I have been able to achieve second one. But I've not been able to figure out a way to generate the first pattern.


Update on @mart's answer:

I defined ABWrap, ABInterface and A as follows:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ABWrap")
public class ABWrap {
    @XmlElements({@XmlElement(name = "A", type = A.class), @XmlElement(name = "B", type = B.class)})
    private List<ABInterface> ab;
}

public interface ABInterface { }

public class A implements ABInterface {
    @XmlValue
    private String a;
}

B is defined similar to A.

main method is as follows:

public class Application {

    public static void main(final String[] args) throws JAXBException {

        JAXBContext jaxbContext = JAXBContext.newInstance(ABWrap.class);
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        A a = new A("a");
        B b = new B("b");
        ABWrap abWrap = new ABWrap(Arrays.asList(a, b));
        marshaller.marshal(abWrap, System.out);
    }
}

But this solution failed with following error: (jaxbpoc is project name)

If a class has @XmlElement property, it cannot have @XmlValue property.
this problem is related to the following location:
    at private java.lang.String ...jaxbpoc.A.a
    at ...jaxbpoc.A
    at private java.util.List ...jaxbpoc.ABWrap.ab
    at ...jaxbpoc.ABWrap
this problem is related to the following location:
    at public java.lang.String ...A.getA()
    at ...jaxbpoc.A
    at private java.util.List ...jaxbpoc.ABWrap.ab
    at ...jaxbpoc.ABWrap
If a class has @XmlElement property, it cannot have @XmlValue property.
this problem is related to the following location:
    at private java.lang.String ...jaxbpoc.B.b
    at ...jaxbpoc.B
    at private java.util.List ...jaxbpoc.ABWrap.ab
    at ...jaxbpoc.ABWrap
    ....
    ....
Class has two properties of the same name "a"
this problem is related to the following location:
    at public java.lang.String ...jaxbpoc.A.getA()
    at ...jaxbpoc.A
    at private java.util.List ...jaxbpoc.ABWrap.ab
    at ...jaxbpoc.ABWrap
this problem is related to the following location:
    ....
    ....

回答1:


You could do this:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ABWrap")
public class ABWrap {
    @XmlElements({
            @XmlElement(name="A", type = A.class),
            @XmlElement(name="B", type = B.class),
    })
    private List<Letter> letters;
}

And A, B would look something like this:

public class A implements Letter {
    @XmlValue
    private String a;
}

And a common interface for A,B that doesn't do much:

public interface Letter { }

Update:

As I mentioned in the comment, I tried XML to POJO and vice versa and it worked. I paste here the simple programs I used to test, so please let me know how it works for you, so I can explore further.

XmlToPojo:

public static void main(String[] args) {
        try {
            File file = new File("AB.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(ABWrap.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            ABWrap pojo = (ABWrap) jaxbUnmarshaller.unmarshal(file);
        } catch (JAXBException e) {
            e.printStackTrace();
        }

    }

And POJO to xml:

public static void main(String[] args) {
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(ABWrap.class);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            A a = new A("testA");
            B b = new B("testB");
            ABWrap abWrap = new ABWrap(Arrays.asList(a, b));
            marshaller.marshal(abWrap, System.out);

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }


来源:https://stackoverflow.com/questions/48631031/jaxb-jackson-sequence-of-two-elements-without-parent-tag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!