我正面临使用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 + '\'';
}
}
}