JAXB: XmlAdapter for List<Object> items
Asked Answered
M

1

8

Does anybody know how to attach custom XmlAdapter to objects contained in heterogenous list (like List)? For example - suppose we have a container class with a list of miscelaneous objects:

@XmlRootElement(name = "container")
public class Container {
    private List<Object> values = new ArrayList<Object>();

    @XmlElement(name = "value")
    public List<Object> getValues() {
        return values;
    }

    public void setValues(List<Object> values) {
        this.values = values;
    }   
}

If we put String-s, Integer-s and so on they will be mapped by default. Now suppose we want to put a custom object:

public class MyObject {
    //some properties go here   
}

The obvious solution is to write a custom adapter:

public class MyObjectAdapter extends XmlAdapter<String, MyObject> {
    //marshalling/unmarshalling
}

But unfortunately it doesn't work with package-level @XmlJavaTypeAdapter - adapter just never called so marhalling fails. And I can't apply it to getValues() directly because there can be other types of objects. @XmlJavaTypeAdapter only works if I have a field of MyObject type in Container (also with package-level annotaton):

public class Container {
    private MyObject myObject;
}

But this is not what I want - I want a list of arbitrary objects. I'm using standard Sun's JAXB implementation:

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.3-1</version>
</dependency>

Any ideas how to do the mapping?

P.S.: One small clarification - I'd like to avoid annotating MyObject with JAXB annotations. It may be a class from third-party library which is not under my control. So any changes should be outside of MyObject.

Mello answered 6/3, 2013 at 16:19 Comment(1)
A ContextResolver could be a good solution here...Kinser
E
1

You could try to change your MyObjectAdapter so that extends XmlAdapter<String, List<Object>>. So it should look something like this:

public class MyObjectAdapter extends XmlAdapter<String, List<Object>> {
    //marshalling/unmarshalling
}

When you also add a XmlJavaTypeAdapter annotation to the getter in your Container class, it should work.

@XmlRootElement(name = "container")
public class Container {
    private ArrayList<Object> values = new ArrayList<Object>();

    @XmlElement(name = "value")
    @XmlJavaTypeAdapter(MyObjectAdapter.class)
    public ArrayList<Object> getValues() {
        return values;
    }

    public void setValues(ArrayList<Object> values) {
        this.values = values;
    }   
}
Ea answered 5/12, 2013 at 14:28 Comment(1)
Can you please elaborate your marshalling code. As I have same scenario to implement and to create the XML structure containing list of object and I have already used XmlAdapter<String, List<Object>> but resulting XML is containing only 1 object instead list of objects. Here is my question - #51590074 Thanks.!Peloquin

© 2022 - 2024 — McMap. All rights reserved.