How to provide JACKSON using namespace-mapper in code?

I am trying to serialize the generated JAXB class. With Jettison, I can create a hash map that matches XML namespaces with any JSON prefix. With Jettison, I also get case sensitivity right in serialization. With JACKSON, it's all lowercase. So it seems Jettison can better understand XMLRootElement(name=…) .

How to make JACKSON better understand JAXB annotations like XMLRootElement ?

How can I provide JACKSON using an XML space and a JSON namespace?

0
source share
2 answers

Note. I am EclipseLink JAXB (MOXy) and a member of the JAXB Expert Group (JSR-222) .

EclipseLink MOXy is a JAXB compatible implementation (JSR-222). In EclipseLink 2.4.0, we introduced JSON binding. Since MOXy is a JAXB implementation, you will find that MOXy JSON output is very consistent with XML output based on the same metadata. I will give an example below.


DOMAIN MODEL

Below is the domain model that I will use for this answer. For more information on specifying namespace information in the JAXB model, see: http://blog.bdoughan.com/2010/08/jaxb-namespaces.html

package info

 @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.*; 

Customer

 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 PROCESSING

The following is an example of how the domain model matches the XML representation.

Demo

 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 / output

 <?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 PURPOSE

Namespaces are not a JSON concept, so I would recommend not simulating them if you can avoid it. Below I will demonstrate that MOXy does not need them. Pay attention to the same domain model and the JAXBContext used here, which was used for the XML document with namespaces.

jaxb.properties

To specify MOXy as the JSON provider, you need to include a file named jaxb.properties in the same package as your domain model, with the following entry (see: <a3> ).

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

Demo

To enable JSON binding, the MEDIA_TYPE property must be enabled on Marshaller and 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 / output

The following is the entry and exit from running the demo code. Note that there is no simulated namespace information in the JSON document.

 { "customer" : { "firstName" : "Jane", "lastName" : "Doe" } } 

JSON HANDLING - WITH MODELED PURPOSES

Demo

If you really want to simulate namespaces in your JSON document, you can use the NAMESPACE_PREFIX_MAPPER property for Marshaller and Unmarshaller for this.

 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 / output

 { "a.customer" : { "a.firstName" : "Jane", "b.lastName" : "Doe" } } 

FOR FURTHER INFORMATION

+1
source

JSON has no namespaces, unlike XML. So why do you think you need namespace matching? Data binding means mapping between Java POJO and a data format using format functions. For XML, this includes namespaces, selection of elements versus attributes, etc. With JSON, most of this complexity is removed, which means that property names are used as is.

Regarding JAXB annotations: Jackson has its own set of annotations that match better, but if you want to use JAXB annotations as an additional or alternative source of configuration, you will need to use the JAXB Annotation Module . But as for using XMLRootElement , there is no need for JSON: JSON objects have no name.

I don’t know what you mean by “getting sensitivity to the matter right in serialization” - right in what sense? What is the problem? You will need to give an example of the definition of POJO, as well as the expected JSON.

Finally, keep in mind that for JSON and XML notation there is no need to look alike. These are different data formats with different logical data models and, of course, different mappings: for example, JSON has its own difference between arrays and objects; whereas XML should use Elements for both. And XML has namespaces, attributes that JSON lacks. They lead to various natural mappings, and attempts to "unify" the two lead to several unnatural results for one or the other, or both. In the case of Jettison (and the frameworks that use it), this is ugly JSON ("franken-JSON").

0
source

All Articles