I'm trying to bind XML and JSON using the same JAXB annotations (using the JaxbAnnotationModule).



XML <--> JAXB <--> Jackson <--> JSON


I have to use the JAXB annotation and cannot alter them. My problem is that some XMLs convert to the generic class JAXBElement<T> instead of a class T directly. That leads to the JSON output:



{
"JAXBElement":{
"name":"{http://ift.tt/1Ah7mkZ",
"declaredType":"net.opengis.wps.v_1_0_0.WPSCapabilitiesType",
"scope":"javax.xml.bind.JAXBElement$GlobalScope",
"value":{
"ProcessOfferings":{ },
"Languages":{ },
"ServiceIdentification":{ },
"ServiceProvider":{ },
"OperationsMetadata":{ },
"version":"1.0.0",
"updateSequence":"1",
"service":"WPS",
"lang":"en-US"
},
"nil":false,
"globalScope":true,
"typeSubstituted":false
}
}


While I instead want:



{
"Capabilities":{
"ProcessOfferings":{ },
"Languages":{ },
"ServiceIdentification":{ },
"ServiceProvider":{ },
"OperationsMetadata":{ },
"version":"1.0.0",
"updateSequence":"1",
"service":"WPS",
"lang":"en-US"
}
}


The real object of type T is wrapped by an JAXBElement. This may happen for some root elements and nested anywhere in the object tree as well. If I call getValue() on that I'll get the real object. But I can't do this when the JAXBElement<T> is not the root element since Jackson is the only interpreter between JAXB and JSON and I can neither alter the JAXB-Binding nor the created objects (some other parts of the code use them, too).


So what I found what might solve the problem are MixIns:



// a mixin annotation that overrides the handling for the JAXBElement
public static interface JAXBElementMixin<T> {
@JsonValue
Object getValue();
}

ObjectMapper mapper = new ObjectMapper();
JaxbAnnotationModule module = new JaxbAnnotationModule();
mapper.registerModule(module);
mapper.addMixInAnnotations(JAXBElement.class, JAXBElementMixin.class);


That solves the problem of the additional elements but causes the name of the object to be JAXBElement instead of T (in my case Capabilities):



{
"JAXBElement":{ // <------ Should be 'Capabilities' because of type JAXBElement<Capabilities>
"ProcessOfferings":{ },
"Languages":{ },
"ServiceIdentification":{ },
"ServiceProvider":{ },
"OperationsMetadata":{ },
"version":"1.0.0",
"updateSequence":"1",
"service":"WPS",
"lang":"en-US"
}
}


The questions:


Any idea what I can do (maybe annotate JAXBElementMixin<T>) to get the correct type Capabilities as object name (there are other classes instead of Capabilities that can be placed as T, too)?


Any other idea how to skip the serialization of any JAXBElement<T> anywhere in the object tree and continue with the serialization of the object behind its getValue() method?


No comments:

Post a Comment