我有一个 Web 应用程序,可以在其中从域对象生成 POJO。我的一个域对象包含一个 map ,并且 JAXB 生成以下架构:
<xs:element name="persons">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="key" minOccurs="0" type="xs:string"/>
<xs:element name="value" minOccurs="0" type="person"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
这是从 HashMap<String, Person>
生成的人员:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "personConfiguration", propOrder = {
"persons",
})
@XmlRootElement(name = "personConfiguration")
public class PersonConfiguration
{
@XmlElement(required = true)
protected PersonConfiguration.Persons persons;
/**
* Gets the value of the persons property.
*
* @return
* possible object is
* {@link PersonConfiguration.Persons }
*
*/
public PersonConfiguration.Persons getPersons() {
return persons;
}
/**
* Sets the value of the persons property.
*
* @param value
* allowed object is
* {@link PersonConfiguration.Persons }
*
*/
public void setPersons(PersonConfiguration.Persons value) {
this.persons = value;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"entry"
})
public static class Persons
{
protected List<PersonConfiguration.Persons.Entry> entry;
/**
* Gets the value of the entry property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the entry property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getEntry().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link PersonConfiguration.Persons.Entry }
*
*
*/
public List<PersonConfiguration.Persons.Entry> getEntry() {
if (entry == null) {
entry = new ArrayList<PersonConfiguration.Persons.Entry>();
}
return this.entry;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"key",
"value"
})
public static class Entry
{
protected String key;
protected Person value;
/**
* Gets the value of the key property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getKey() {
return key;
}
/**
* Sets the value of the key property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setKey(String value) {
this.key = value;
}
/**
* Gets the value of the value property.
*
* @return
* possible object is
* {@link Person }
*
*/
public Person getValue() {
return value;
}
/**
* Sets the value of the value property.
*
* @param value
* allowed object is
* {@link Person }
*
*/
public void setValue(Person value) {
this.value = value;
}
}
}
}
正如人们所看到的,JAXB 添加了这一额外级别的间接条目 -> 键、值。难题的其他部分是 Spring MVC、使用 JSON 对象的 REST 调用。
现在,基于 XML 的 REST 调用可以与上面的对象架构一起正常工作,但是当使用具有相同架构的 JSON 消息发送相同的调用时,我会收到 JSONMappingException。
你知道为什么会发生这种情况吗?
最佳答案
注意:我是EclipseLink JAXB (MOXy) JAXB (JSR-222) 的领导者和成员专家组。
当使用不同的 XML 和 JSON 绑定(bind)提供程序时,很难保持 XML 和 JSON 表示的一致性。下面的示例说明了如何使用 MOXy 作为 XML 和 JSON 提供程序来简化这一过程,并将所有映射信息作为 JAXB 注释提供。
根
下面是一个示例域对象,其中 persons
字段将从您的问题生成 XML 架构片段。
package forum13784163;
import java.util.Map;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
Map<String, Person> persons;
}
人
下面是您的 Person
类的示例。请注意我如何将 id
字段映射到 XML 属性。
package forum13784163;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class Person {
@XmlAttribute
int id;
String name;
int age;
}
jaxb.properties
要使用 MOXy 作为 JAXB 提供程序,您需要在与域模型相同的包中包含一个名为 jaxb.properties
的文件,其中包含以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)。
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
input.json
如果 MOXy 用作 JSON 绑定(bind)提供程序,则 JSON 表示形式如下所示。
{
"persons" : {
"entry" : [ {
"key" : "Jane",
"value" : {
"id" : 123,
"name" : "Jane",
"age" : 30
}
} ]
}
}
演示
在下面的演示代码中,JSON 被解码为对象,然后这些相同的对象被编码为 XML。这是通过包含一组元数据的一个 JAXBContext
完成的。
package forum13784163;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
StreamSource json = new StreamSource("src/forum13784163/input.json");
Root root = unmarshaller.unmarshal(json, Root.class).getValue();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
输出
下面是生成的 XML。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<persons>
<entry>
<key>Jane</key>
<value id="123">
<name>Jane</name>
<age>30</age>
</value>
</entry>
</persons>
</root>
了解更多信息
关于rest - JAXB Jackson - 如何处理 map ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13784163/