I'm using Jersey to create a REST web service for a server component.
The JAXB-annotated object I want to serialize in a list looks like this:
@XmlRootElement(name = "distribution")
@XmlType(name = "tDistribution", propOrder = {
"id", "name"
})
public class XMLDistribution {
private String id;
private String name;
// no-args constructor, getters, setters, etc
}
I have a REST resource to retrieve one distribution which looks like this:
@Path("/distribution/{id: [1-9][0-9]*}")
public class RESTDistribution {
@GET
@Produces("application/json")
public XMLDistribution retrieve(@PathParam("id") String id) {
return retrieveDistribution(Long.parseLong(id));
}
// business logic (retrieveDistribution(long))
}
I also have a REST resource to retrieve a list of all distributions, which looks like this:
@Path("/distributions")
public class RESTDistributions {
@GET
@Produces("application/json")
public List<XMLDistribution> retrieveAll() {
return retrieveDistributions();
}
// business logic (retrieveDistributions())
}
I use a ContextResolver to customize JAXB serialization, which is currently configured like this:
@Provider
@Produces("application/json")
public class JAXBJSONContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
public JAXBJSONContextResolver() throws Exception {
JSONConfiguration.MappedBuilder b = JSONConfiguration.mapped();
b.nonStrings("id");
b.rootUnwrapping(true);
b.arrays("distribution");
context = new JSONJAXBContext(b.build(), XMLDistribution.class);
}
@Override
public JAXBContext getContext(Class<?> objectType) {
return context;
}
}
Both REST resources work, as well as the context resolver. This is an example of output for the first one:
// path: /distribution/1
{
"id": 1,
"name": "Example Distribution"
}
Which is exactly what I want. This is an example of output for the list:
// path: /distributions
{
"distribution": [{
"id": 1,
"name": "Sample Distribution 1"
}, {
"id": 2,
"name": "Sample Distribution 2"
}]
}
Which is not quite what I want.
I don't understand why there is an enclosing distribution
tag there. I wanted to remove it with .rootUnwrapping(true)
in the context resolver, but apparently that only removes another enclosing tag. This is the output with .rootUnwrapping(false)
:
// path: /distribution/1
{
"distribution": {
"id": 1,
"name": "Example Distribution"
}
} // not ok
// path: /distributions
{
"xMLDistributions": {
"distribution": [{
"id": 1,
"name": "Sample Distribution 1"
}, {
"id": 2,
"name": "Sample Distribution 2"
}]
}
}
I also had to configure .arrays("distribution")
to always get a JSON array, even with only one element.
Ideally, I'd like to have this as an output:
// path: /distribution/1
{
"id": 1,
"name": "Example Distribution"
} // currently works
// path: /distributions
[{
"id": 1,
"name": "Sample Distribution 1"
}, {
"id": 2,
"name": "Sample Distribution 2"
}]
I tried to return a List<XMLDistribution>
, a XMLDistributionList
(wrapper around a list), a XMLDistribution[]
, but I couldn't find a way to get a simple JSON array of distributions in my required format.
I also tried the other notations returned by JSONConfiguration.natural()
, JSONConfiguration.mappedJettison()
, etc, and couldn't get anything resembling what I need.
Does anyone know if it is possible to configure JAXB to do this?
See Question&Answers more detail:
os