Java – JAXB: how to customize XML serialization of two fields
I have a legacy class with many public double fields Use double MAX_ Value initializes all double fields to indicate that they are empty (the legacy serialization code is to ignore the field. If the field is equal to double.max_value, it will not be serialized)
We will now try to serialize this class into XML. XML using JAXB Marshall It works normally except that we want to block it to be equal to double MAX_ The field of value generates XML
Instead of using a separate JAXB schema, we just use various javax xml. bind. Annotation annotations marks our class If a schema is used, you can add a < javatype > element to specify a custom datatype converter Is there a way to do this using annotations or programmatically?
After trying the following recommended method, I still can't get the xmladapter:
@XmlJavaTypeAdapters({ @XmlJavaTypeAdapter(value=EmptyDoubleValueHandler.class,type=Double.class),@XmlJavaTypeAdapter(value=EmptyDoubleValueHandler.class,type=double.class)}) package tta.penstock.data.iserver; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
My top course is: TTA penstock. data. iserver. Orderblotter, which contains an extension com eztech. TTA of orderresponse penstock. data. iserver. Orderresponsewrappers list All double fields are included in com eztech. In orderresponse
My unit test code does the following:
JAXBContext context = JAXBContext.newInstance(new Class[] { OrderBlotter.class,OrderResponseWrapper.class,OrderResponse.class}); Marshaller marshaller = context.createMarshaller(); StringWriter stringWriter = new StringWriter(); marshaller.marshal(blotter,stringWriter); System.out.println("result xml=\n" + stringWriter.toString());
However, double values still cannot be handled by the xmladapter I know I missed something basic, but I'm not sure what it is
Solution
You can use xmladapter:
> http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
XmlAdapter
package example; import javax.xml.bind.annotation.adapters.XmlAdapter; public class DoubleAdapter extends XmlAdapter<Double,Double>{ @Override public Double unmarshal(Double v) throws Exception { return v; } @Override public Double marshal(Double v) throws Exception { if(Double.MAX_VALUE == v) { return null; } else { return v; } } }
Model object
package example; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement public class Root { @XmlJavaTypeAdapter(DoubleAdapter.class) public Double maxDouble = Double.MAX_VALUE; @XmlJavaTypeAdapter(DoubleAdapter.class) public Double aDouble = 123d; }
Demo code
package example; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true); marshaller.marshal(new Root(),System.out); } }
UPDATE
Staxman's advice is very good If you specify the following package level annotations, you can avoid annotating all double attributes individually
package-info. java
@XmlJavaTypeAdapters({ @XmlJavaTypeAdapter(type=Double.class,value=DoubleAdapter.class) }) package example; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;