JAXB MOXy marshalling和unmarshalling通用对象集合(包括字符串和原始包装器)

时间:2015-03-18 08:59:11

标签: java collections jaxb moxy xmlanyelement

我正面临使用MOXy编组和解组集合的问题。集合可以包含任何类型的元素。在下面的测试用例中,我试图编组,然后取消对字符串的收集。

测试生成以下输出:

Going with type: APPLICATION_XML
Original XmlCollection: [one, two, three]
Marshaled as application/xml: <?xml version="1.0" encoding="UTF-8"?><collection>onetwothree</collection>

Unmarshaled XmlCollection: []
Going with type: APPLICATION_JSON
Original XmlCollection: [one, two, three]
Marshaled as application/json: {"value":["one","two","three"]}
Unmarshaled XmlCollection: []

在XML情况下,我希望将集合元素序列化为包含值的嵌套列表xml元素,但事实并非如此。

在JSON生成代码的情况下,代码看起来不错,但我希望对象能够正确地解组,这并没有发生。

当我使用Collection of SimpleObject运行测试时(取消注释行标记为Simple对象),所有内容都像sharm一样工作,输出产生如下:

Going with type: APPLICATION_XML
Original XmlCollection: [stringField='one', stringField='two', stringField='three']
Marshaled as application/xml: <?xml version="1.0" encoding="UTF-8"?><collection><simpleObject><stringField>one</stringField></simpleObject><simpleObject><stringField>two</stringField></simpleObject><simpleObject><stringField>three</stringField></simpleObject></collection>
Unmarshaled XmlCollection: [stringField='one', stringField='two', stringField='three']
Going with type: APPLICATION_JSON
Original XmlCollection: [stringField='one', stringField='two', stringField='three']
Marshaled as application/json: {"simpleObject":[{"stringField":"one"},{"stringField":"two"},{"stringField":"three"}]}
Unmarshaled XmlCollection: [stringField='one', stringField='two', stringField='three']

感谢任何线索,以及如何正确完成此映射。

测试用例:

public class TestCase {
    // Element name holding value of primitive types
    public static final String VALUE_ELEMENT = "value";
    // Attribute prefix in JSON
    public static final String ATTRIBUTE_PREFIX = "@";

    public static void main(String... args) {
        try {
            for (MediaType type : new MediaType[]{MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) {
                System.out.println("Going with type: " + type);
                JAXBContext context = (JAXBContext) JAXBContextFactory.createContext(
                    new Class[]{
                        XmlCollection.class,
//  Simple Object                          SimpleObject.class,
                    },
                    Collections.emptyMap());

                Marshaller marshaller = context.createMarshaller();
                marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, type);
                marshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
                marshaller.setProperty(MarshallerProperties.JSON_ATTRIBUTE_PREFIX, ATTRIBUTE_PREFIX);
                marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, VALUE_ELEMENT);
                marshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);

                XmlCollection original = new XmlCollection(Arrays.asList("one", "two", "three"));
// Simple object                XmlCollection original = new XmlCollection(Arrays.asList(new SimpleObject("one"), new SimpleObject("two"), new SimpleObject("three")));

                System.out.println("Original " + original.toString());

                StreamResult result = new StreamResult(new StringWriter());
                marshaller.marshal(original, result);
                String generated = result.getWriter().toString();
                System.out.println("Marshaled as " + type.getMediaType() + ": " + generated);

                Unmarshaller unmarshaller = context.createUnmarshaller();
                unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, type);
                unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
                unmarshaller.setProperty(UnmarshallerProperties.JSON_ATTRIBUTE_PREFIX, ATTRIBUTE_PREFIX);
                unmarshaller.setProperty(UnmarshallerProperties.JSON_VALUE_WRAPPER, VALUE_ELEMENT);
                unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);


                XmlCollection unmarshaled = unmarshaller.unmarshal(new StreamSource(new StringReader(generated)), XmlCollection.class).getValue();
                System.out.println("Unmarshaled " + unmarshaled.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @XmlRootElement(name = "collection")
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class XmlCollection<T> {
        @XmlAnyElement(lax = true)
        private Collection collection = new ArrayList();

        public XmlCollection() {
        }

        public XmlCollection(Collection<T> collection) {
            this.collection.addAll(collection);
        }

        public Collection<T> getCollection() {
            return collection;
        }

        @Override
        public String toString() {
            return "XmlCollection: " + collection;
        }
    }

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public static final class SimpleObject{
        @XmlElement
        public String stringField;
        public SimpleObject(){}

        public SimpleObject(String stringField){
            this.stringField = stringField;
        }

        public String getStringField() {
            return stringField;
        }

        public void setStringField(String stringField) {
            this.stringField = stringField;
        }    

       @Override
       public String toString() {
            return "stringField='" + stringField + '\'';
       }
   }
}

0 个答案:

没有答案