XStream serializes null values

Let's pretend that

class Student { String name; int age; String teacher; } 

Then:

 public class App1 { public static void main(String[] args) { Student st = new Student(); st.setName("toto"); XStream xs = new XStream(); xs.alias("student",Student.class); System.out.println(xs.toXML(st)); } 

}

Gives me:

 <student> <name>toto</name> <age>0</age> </student> 

Is there a way to handle null values? I mean:

 <student> <name>toto</name> <age>0</age> <teacher></teacher> </student> 

Maybe if I do

 st.setTeacher(""); 

but not if the teacher is null.

I tried using a custom converter, but it seems that null values ​​are not sent to the converter.

+7
source share
3 answers

I am using XStream 1.4.7, the annotation @XStreamAlias ​​for custom field names, @XStreamConverter for custom converters (to represent dates and other custom beans). However, a custom converter for zero values ​​was not even called. My goal was to serialize all fields of an object, including null, I did not need to untie XML.

I managed to do this by creating a custom ReflectionConverter. I extended the ReflectionConverter from the XStream library and tried the doMarshal method. The only thing I changed is the call to the writeField method for null info.values:

 new Object() { { for (Iterator fieldIter = fields.iterator(); fieldIter.hasNext();) { FieldInfo info = (FieldInfo) fieldIter.next(); if (info.value != null) { //leave the code unchanged ... } else { //add this to write null info.value to xml Log.info("MyCustomReflectionConverter -> serialize null field: " + info.fieldName); writeField(info.fieldName, null, info.type, info.definedIn, info.value); } } //... leave the rest of the code unchanged } }; 

After that I created such an instance of xStream (it is very important to register your converter with a very low priority):

 StaxDriver driver = new StaxDriver(new NoNameCoder()) { @Override public StaxWriter createStaxWriter(XMLStreamWriter out) throws XMLStreamException { // the boolean parameter controls the production of XML declaration return createStaxWriter(out, false); } }; XStream xStream = new XStream(driver); xStream.autodetectAnnotations(true);//needed to process aliases //register MyCustomReflectionConverter MyCustomReflectionConverter reflectionConverter = new MyCustomReflectionConverter (xStream.getMapper(), new SunUnsafeReflectionProvider()); xStream.registerConverter(reflectionConverter, XStream.PRIORITY_VERY_LOW); 

Thanks to Mark Nabours for his solution here.

Hope this helps. Has anyone found a better solution for this?

+2
source

First of all, provide the getter and setter methods in the Student class as follows:

 public class Student{ String name; int age; String teacher; public void setName(String name){ this.name = name; } public String getName(){ return name; } ....... ......//Like that mention other getter and setter method } 

Now you need to create the converter class as follows:

 public class StudentConverter implements Converter{ public boolean canConvert(Class clazz) { return clazz.equals(Test.class); } public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Student student = (Student ) value; writer.startNode("name"); writer.setValue(test.getName()); writer.endNode(); writer.startNode("age"); writer.setValue(test.getAge()); writer.endNode(); writer.startNode("teacher"); writer.setValue(""); writer.endNode(); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Student student = new Student(); test.setName(reader.getNodeName()); test.setAge(reader.getNodeName()); test.setTeacher(reader.getNodeName()); return student; } } Your main class will the like that: public class App1{ public static void main(String args[]) { XStream stream = new XStream(new StaxDriver()); Student st = new Student(); st.setName("ABC"); t.setAge(21); stream.registerConverter(new StudentConverter()); stream.alias("student", Student.class); System.out.println(stream.toXML(st)); } } 

Hope this is your answer .... Happy learning :)

+1
source

You can put an empty string

 String teacher = ""; 

Or optimized :)

 String teacher = StringUtils.EMPTY; 
0
source

All Articles