2012-11-03 31 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

相關問題