XML serialization in Java?
2008 Answer
The "Official" Java API for this is now JAXB - Java API for XML Binding. See Tutorial by Oracle. The reference implementation lives at http://jaxb.java.net/
2018 Update
Note that the Java EE and CORBA Modules are deprecated in SE in JDK9 and to be removed from SE in JDK11. Therefore, to use JAXB it will either need to be in your existing enterprise class environment bundled by your e.g. app server, or you will need to bring it in manually.
A way to serialize an into an XML with attributes in java
You can use JAXB, with @XmlAnyElement
for support of elements with arbitrary names.
The following works natively with Java 8. For Java 7, the stream logic in toString()
needs to be changed to regular for
loop. For Java 9+, where JAXB was removed, a JAXB library is needed.
@XmlRootElement(name = "Person")
@XmlAccessorType(XmlAccessType.NONE)
class Person {
private String version;
private List<Element> properties;
@XmlAttribute
public String getVersion() {
return this.version;
}
public void setVersion(String version) {
this.version = version;
}
@XmlElementWrapper(name = "properties")
@XmlAnyElement
public List<Element> getProperties() {
return this.properties;
}
public void setProperties(List<Element> properties) {
this.properties = properties;
}
public void addProperty(String name, String value) {
try {
Element elem = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument().createElement(name);
elem.setTextContent(value);
if (this.properties == null)
this.properties = new ArrayList<>();
this.properties.add(elem);
} catch (ParserConfigurationException e) {
throw new IllegalStateException(e);
}
}
@Override
public String toString() {
String propertiesAsString = this.properties.stream()
.map(e -> e.getLocalName() + ": \"" + e.getTextContent() + "\"")
.collect(Collectors.joining(", ", "[", "]"));
return "Person[version=" + this.version + ", properties=" + propertiesAsString + "]";
}
}
Test
Person person = new Person();
person.setVersion("xyz");
person.addProperty("name", " John");
person.addProperty("city", "nyc");
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter xml = new StringWriter();
marshaller.marshal(person, xml);
System.out.println(xml);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Person person2 = (Person) unmarshaller.unmarshal(new StringReader(xml.toString()));
System.out.println(person2);
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Person version="xyz">
<properties>
<name> John</name>
<city>nyc</city>
</properties>
</Person>
Person[version=xyz, properties=[name: " John", city: "nyc"]]
Easy XML Serializer for Java
My vote would be for XStream. The lack of generics support is a small price to pay for the amount of flexibility it offers. You can also easily implement generics by serializing the generic class type at serialization time, or build this into your domain objects. E.g.
class Customer
{
List<Order> orders;
public List<Order> getOrders()
{
return orders;
}
}
In the stream, the element type denotes the type of each object. When the type is an abstract type or interface, the element listed with the implementing class, unless that has been specified as the default for that interface type. (E.g. ArrayList as the default for instances of static type List.)
Generics are "rose coloured glasses" in java - they don't really change what you are seeing, just how you see it. The objects would be sent over the wire exactly the same if they were sent with generics support or not.
Manually XML-serializing a Java object
You can do
private byte[] encode(YourObject obj)
{
byte[] bytes = null;
try
{
YourObject vsNew = new YourObject(obj)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream out = new GZIPOutputStream(baos);
XMLEncoder encoder = new XMLEncoder(out);
encoder.writeObject(vsNew);
encoder.close();
bytes = baos.toByteArray();
}
catch (Exception e)
{
_log.error("Exception caught while encoding/zipping ", e);
}
return bytes;
}
/*
* Decode the report definition blob back to the
* ScheduledReport object.
*/
private YourObject decode(byte[] bytes)
{
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
YourObject vSNew = null;
try
{
GZIPInputStream in = new GZIPInputStream(bais);
XMLDecoder decoder = new XMLDecoder(in);
vSNew = (YourObject)decoder.readObject();
decoder.close();
}
catch (Exception e)
{
_log.error("IOException caught while decoding/unzipping ", e);
}
return vSNew ;
}
Best Practice for Serialize/Deserialize from Java to XML
I've always had positive experiences with XStream:
http://x-stream.github.io/tutorial.html#to-xml
As you can see, it's simple to use.
I haven't actually used XStream with Generics (I've only ever used it for simple JavaBean type classes), but Google seems to suggest it handles them without problems. e.g. http://techo-ecco.com/blog/xstream-spring-ws-oxm-and-generics/
Serialize Object To XML in java ignores some variable fields of my object
Two things worth noting:
- XMLEncoder does not look at private fields. It only looks at matching pairs of 'get' and 'set' methods (or 'is' and 'set' methods). You have a
getNullableState
method but the set-method does not match; you should renamesetNullable
tosetNullableState
. - XMLEncoder only writes values for properties which are different from their initial state. The initial state of each property is whatever value it has when the object is initially constructed.
So, one way to force a property value to be written is to make sure it has a value that's different from what it had when the object was constructed.
If you want to always write XML for every property, you may want to consider using JAXB instead of XMLEncoder.
Java+Jackson+XML: serialize a java object properties as XML elements with same names
You need to mark those properties as attributes like this:
public class Point {
@JacksonXmlProperty(isAttribute = true)
private Integer x;
@JacksonXmlProperty(isAttribute = true)
private Integer y;
//getters/setters
}
Related Topics
Android - Copy Assets to Internal Storage
Android What Is Wrong with Openfileoutput
How to Convert Date to a Particular Format in Android
Error Inflating Class Com.Google.Ads.Adview
Android Geocoder Getfromlocationname Always Returns Null
Wait Until Firebase Retrieves Data
Calculate Difference Between Two Times in Android
Alertdialog from Within Broadcastreceiver? Can It Be Done
More Efficient Way for Pausing Loop Wanted
How to Save Image File in Android Oreo Update. How to Do It
How to Parse This JSON in Android
Android: Realm + Retrofit 2 + Gson
Navigation Drawer Closes on Click
Android:Java.Lang.Outofmemoryerror:
How to Read Firestore Sub-Collection and Pass It to Firestorerecycleroptions