I have a legacy class, with a lot of public double fields. All double fields are initialized with Double.MAX_VALUE to indicate that they are empty. (The legacy serialization is coded to ignore the field and not serialize if field is equals to Double.MAX_VALUE).
We are now trying to serialize this class to Xml using JAXB Marshaller. It is working fine, except that we want to prevent generating Xml for fields which equal Double.MAX_VALUE.
We aren't using a separate JAXB schema, just marking up our classes with various javax.xml.bind.annotation Annotations. If a schema is used, you can add a <javaType> element to specify a custom DataType converter. Is there any way to do this using Annotations or programmatically?
After trying approach recommended below, I still can't get XmlAdapter picked up:
@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 level class is: tta.penstock.data.iserver.OrderBlotter, which contains a list of tta.penstock.data.iserver.OrderResponseWrappers which extends com.eztech.OrderResponse. All the double fields are contained in com.eztech.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());
But the double values still don't get handled by the XmlAdapter. I know I'm missing something basic, but I'm not sure what it is.
You could use an XmlAdapter:
The 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;
}
}
}
The 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 suggestion is a good one. If you specify the following package level annotation you can avoid the need of individually annotating all the Double properties
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;
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