2012-11-03 32 views
0

我想序列化一个JAXB生成的类。通过Jettison,我可以创建一个将XML名称空间映射到任何JSON前缀的哈希映射。通过Jettison,我还可以在序列化中区分大小写。有了JACKSON,全是小写字母。所以,似乎Jettison能够更好地理解XMLRootElement(name=…)如何使用代码中的namespace-mapper提供JACKSON?

如何让JACKSON更好地理解像XMLRootElement这样的JAXB注释?

如何提供带有XML的JACKSON → JSON命名空间映射器?

+1

您需要包含您尝试使用的POJO类。也可能是你期望的JSON。 – StaxMan

回答

1

备注:我是EclipseLink JAXB (MOXy)的领导者和JAXB (JSR-222)专家组的成员。

EclipseLink MOXy是符合JAXB(JSR-222)标准的实现。在EclipseLink 2.4.0中,我们引入了JSON绑定。由于MOXy是JAXB实现,您会发现MOXy生成的JSON输出将与基于相同元数据的XML输出非常一致。我将在下面举例说明。


域模型

下面是我将使用这个答案的域模型。有关在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 HANDLING - WITHOUT NAMESPACES

命名空间不是JSON概念,所以如果可以避免这种情况,我建议不要模拟它们。下面我将演示MOXy不需要它们。请注意,此处使用完全相同的域模型,JAXBContext用于具有名称空间的XML文档。

jaxb。性能

要指定莫西为您的JSON提供你需要包括一个名为在同一个包jaxb.properties与下面进入你的领域模型文件(见:http://blog.bdoughan.com/search/label/jaxb.properties)。

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

演示

要启用JSON绑定MEDIA_TYPE属性需要在MarshallerUnmarshaller被启用。

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处理 - 用模拟NAMESPACES

演示

如果你真的想模仿你的JSON文件中的命名空间,你可以利用上的NAMESPACE_PREFIX_MAPPER财产MarshallerUnmarshaller这样做。

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" 
    } 
} 

FOR更多信息

+0

非常感谢你提供了非常有用的信息。不过,我们必须使用JACKSON! –

+0

@BehzadPirvali - StaxMan是杰克逊的领导,所以你应该检查他的答案:http://stackoverflow.com/a/13222220/383861 –

0

与XML不同,JSON没有名称空间。那么为什么你觉得你需要命名空间映射?数据绑定意味着使用格式的特征,在Java POJO和数据格式之间进行映射。对于XML,这包括名称空间,元素与属性的选择等等。使用JSON时,大部分这种复杂性都被删除了,这意味着属性名称可以按原样使用。对于JAXB注释:杰克逊拥有自己的一组注释,这些注释匹配得更好,但是如果您确实想使用JAXB注释作为附加或替代配置源,则需要使用JAXB Annotation module。 但是对于使用XMLRootElement,JSON没有必要:JSON对象没有名称。

我不知道你的意思是“在序列化中区分大小写” - 在某种意义上?问题是什么?您将需要提供一个POJO定义以及预期JSON的示例。

最后,请记住,不需要JSON和XML表示法看起来相像。这些是具有不同逻辑数据模型的不同数据格式,自然也有不同的映射:例如,JSON在数组和对象之间具有本地区别;而XML必须使用两者的元素。 XML具有JSON所缺乏的名称空间和属性。这些导致了不同的自然映射,并且试图“统一”这两种导致某种或另一种或两者的某种不自然的结果。在Jettison(以及使用它的框架)的情况下,它是丑陋的JSON(“franken-JSON”)。

+0

非常感谢你的信息丰富的评论,除了:1)如何避免命名冲突没有命名空间? 2)您在* .xsd文件中自动获取JAXB注释,作为运行JAXB的一部分。理想情况下,这些注释也应该推动JSON的创建,你不同意吗? 3)那么,为什么不推荐使用JaxbAnnotationIntrospector?再次感谢 –

+0

(1)避免名称冲突。你会从哪里得到冲突的名字? (也就是说,实际的问题是什么)(2)XSD是针对XML的,而不是针对JSON的,所以它通常不是最优的定义。但是,既然这就是你所拥有的,而且你正在使用JAXB工具,那么是的(可以将其他XSD工具与其他产品一起使用)。 (3)JaxbAnnotationIntrospector绝对不被弃用,但你可能使用的构造函数是?希望这可以帮助! – StaxMan

相关问题