I have a XSD from which I want to support both JSON and XML data formats serialization/deserialization.
I generated my Model classes using xjc
utility.
So uptill now I have handled JSON data by using Jackson JSON library.
I cannot modify my Java classes, so I configured ObjectMapper
with Mix-In annotations
and other features like PropertyNamingStrategy
(changing field names), SerializationFeature.WRAP_ROOT_VALUE
to provide configurations over my serilaization through code.
Now I want to do the same with XML serialization process.
I have read online for various options :
Which is the most suitable for my case (cannot edit my POJOs with annotations, only code configurations allowed) ??
I chose JAXB for my XML serialization/deserialization beacuse I had an XML schema already and wanted XML in a way which JAXB provided being a native XML library. Even though Jackson xml is a good choice too if it suits your needs.
Limitations of the Jackson XML Module:
The XML module in Jackson is by no means designed to be an exact replacement for JAXB. There are certain constructs that will work subtly differently between JAXB and Jackson, and there is no guarantee that Jackson will produce identical XML to JAXB.
Note that, unlike with JSON, the outermost object must be a bean type – it can not be a primitive or wrapper type, an enumeration, or a collection. This is a direct result of how XML works – there’s no way in XML to represent such a top-level value.
By default, Jackson will always use a wrapper element for collections, which is also different to how JAXB works. This is the major way that the XML produced by Jackson is not compatible with the XML produced by JAXB. Of course, the behavior can be configured, using the JacksonXmlElementWrapper annotation for one field or the setDefaultUseWrapper configuration setting on the XmlMapper globally.
Jackson also has no support for working with specific XML Schemas. It’s designed for writing Java Beans first, rather than generating the Java code from pre-existing schemas. Note that this can be solved to an extent by using the JAXB annotation support and generating the beans using the standard xjc tool.
Equally, it has no support for some of the more advanced XML tools – such as XPath or XSLT. If we need this level of support then we should instead use a more full-featured XML solution.
Summary:
If you’re looking for a mature, flexible way of supporting and working with both JSON and XML for the same data, the Jackson XML module is a fantastic library to leverage. It’s not only a solid way to go on its own, but it also has the added benefit of being able to mostly reuse the same configuration for both XML as well as JSON.
Typically, this has to be handled using two different libraries with entirely separate configurations.
Finally, beyond flexibility and ease-of-use, the Jackson team has historically placed a strong emphasis on performance. And given that marshalling and unmarshalling of data is a large part of most web applications, choosing the right library to handle all of that work is critical. That, plus a performance monitoring tool such as Retrace will allow you to get the most out of your app.
References: https://stackify.com/java-xml-jackson/
My vote is for #2 Jackson library + Jackson-dataformat-xml.jar Have a look on the code for JSON and XML, it's just the same with bit change here and there.
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class MainClass {
public static void main(String[] args) throws JsonProcessingException {
// Serialization: java obj to json--> writeValueAsString
// DeSerialization: json to java obj--> ReadValue
XmlMapper mapper1 = new XmlMapper();
ObjectMapper mapper2 = new ObjectMapper();
mapper1.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
mapper2.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
mapper1.enable(SerializationFeature.INDENT_OUTPUT);
mapper2.enable(SerializationFeature.INDENT_OUTPUT);
MyPojo mypojo = new MyPojo();
mypojo.setName("Dhani");
mypojo.setId("18082013");
mypojo.setAge(5);
String jsonStringXML = mapper1.writeValueAsString(mypojo);
String jsonStringJSON = mapper2.writeValueAsString(mypojo);
// takes java class with def or customized constructors and creates JSON
System.out.println("XML is " + "\n" + jsonStringXML + "\n");
System.out.println("Json is " + "\n" + jsonStringJSON);
} }
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
@JsonPropertyOrder({ "name", "age", "id", "note" })
@JacksonXmlRootElement(namespace = "urn:stackify:jacksonxml", localName = "myPOJO")
public class MyPojo {
@JsonProperty("_id")
private String id;
private String name;
private int age;
@JsonIgnore
private String note;
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
} }
<myPOJO xmlns="urn:stackify:jacksonxml">
<name xmlns="">Dhani</name>
<age xmlns="">5</age>
<_id xmlns="">18082013</_id>
</myPOJO>
{
"name" : "Dhani",
"age" : 5,
"_id" : "18082013"
}
I vote for answer #2: using Jackson-dataformat-xml. We were in a similar situation and found that serializing to XML via Jackson was easier than expected. This is because XmlMapper
extends ObjectMapper
so all of our configuration changes (mix-ins, using JavaTimeModule
, etc) could be directly applied to XmlMapper
and they just worked.
You've already configured Jackson to output your data as you require so the hard part is done. I recommend leveraging the effort you've already invested and going with Jackson-dataformat-xml.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With