我正在尝试序列化一个JAXB生成的类。使用Jettison,我可以创建一个哈希映射,将XML名称空间映射到任何JSON前缀。使用Jettison,我也可以在序列化中获得区分大小写。使用JACKSON,它都是小写的。所以,看来Jettison能够更好地理解XMLRootElement(name=…)
。
如何让JACKSON更好地理解XMLRootElement
之类的JAXB注释?
如何为JACKSON提供XML→JSON命名空间映射器?
答案 0 :(得分:2)
注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。
EclipseLink MOXy是一个符合JAXB(JSR-222)的实现。在EclipseLink 2.4.0中,我们引入了JSON绑定。由于MOXy是一个JAXB实现,您会发现MOXy生成的JSON输出与基于相同元数据的XML输出非常一致。我将在下面举例说明。
DOMAIN MODEL
以下是我将用于此答案的域模型。有关在JAXB模型中指定名称空间信息的更多信息,请参阅:http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
的包信息强> 的
@XmlSchema(
namespace="http://www.example.com/A",
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns={
@XmlNs(prefix="a",namespaceURI = "http://www.example.com/A"),
@XmlNs(prefix="b",namespaceURI = "http://www.example.com/B")
}
)
package forum13214306;
import javax.xml.bind.annotation.*;
<强>客户强> 的
package forum13214306;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
String firstName;
@XmlElement(namespace="http://www.example.com/B")
String lastName;
}
XML处理
以下是域模型如何与XML表示形式对应的示例。
的演示强> 的
package forum13214306;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum13214306/input.xml");
Customer customer = (Customer) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
}
}
的 input.xml中/输出强> 的
<?xml version="1.0" encoding="UTF-8"?>
<a:customer xmlns:b="http://www.example.com/B" xmlns:a="http://www.example.com/A">
<a:firstName>Jane</a:firstName>
<b:lastName>Doe</b:lastName>
</a:customer>
JSON处理 - 没有名字
命名空间不是JSON概念,所以如果可以避免这种情况,我建议不要模拟它们。下面我将演示MOXy不需要它们。请注意完全相同的域模型,此处使用的JAXBContext
用于带有名称空间的XML文档。
的 jaxb.properties 强> 的
要将MOXy指定为JSON提供程序,您需要在与域模型相同的程序包中包含名为jaxb.properties
的文件,并带有以下条目(请参阅:http://blog.bdoughan.com/search/label/jaxb.properties)。
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
的演示强> 的
要启用JSON绑定,需要在MEDIA_TYPE
和Marshaller
上启用Unmarshaller
属性。
package forum13214306;
import java.io.File;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
File json = new File("src/forum13214306/input.json");
Customer customer = (Customer) unmarshaller.unmarshal(json);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.marshal(customer, System.out);
}
}
的 input.json /输出强> 的
以下是运行演示代码的输入和输出。请注意JSON文档中没有模拟的命名空间信息。
{
"customer" : {
"firstName" : "Jane",
"lastName" : "Doe"
}
}
JSON处理 - 使用模拟的名字
的演示强> 的
如果您真的想在JSON文档中模拟名称空间,可以利用NAMESPACE_PREFIX_MAPPER
和Marshaller
上的Unmarshaller
属性来执行此操作。
package forum13214306;
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Map<String, String> namespaceToPrefixMap = new HashMap<String, String>(2);
namespaceToPrefixMap.put("http://www.example.com/A", "a");
namespaceToPrefixMap.put("http://www.example.com/B", "b");
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
unmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER, namespaceToPrefixMap);
File json = new File("src/forum13214306/input.json");
Customer customer = (Customer) unmarshaller.unmarshal(json);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, namespaceToPrefixMap);
marshaller.marshal(customer, System.out);
}
}
<强> input.json /输出强>
{
"a.customer" : {
"a.firstName" : "Jane",
"b.lastName" : "Doe"
}
}
更多信息
答案 1 :(得分:0)
与XML不同,JSON没有名称空间。那么为什么你觉得你需要命名空间映射?数据绑定意味着使用格式的特征在Java POJO和数据格式之间进行映射。对于XML,这包括名称空间,元素与属性的选择等。使用JSON,大部分复杂性被删除,这意味着属性名称按原样使用。
对于JAXB注释:Jackson有自己的一组注释可以更好地匹配,但如果您确实希望使用JAXB注释作为附加或替代配置源,则需要使用JAXB Annotation module。
但是对于使用XMLRootElement
,JSON没有必要:JSON对象没有名称。
我不知道你的意思是“在序列化中获得案例敏感性” - 在什么意义上是正确的?问题是什么?您需要提供POJO定义以及预期JSON的示例。
最后,请记住,JSON和XML符号不需要彼此看起来像。这些是具有不同逻辑数据模型的不同数据格式,以及自然不同的映射:例如,JSON在数组和对象之间具有本机区别;而XML必须同时使用Elements。 XML具有JSON缺少的名称空间和属性。这些导致不同的自然映射,并且试图“统一”两者导致对于一个或另一个或两者的某种不自然的结果。对于Jettison(以及使用它的框架),它是丑陋的JSON(“franken-JSON”)。