Spring REST with both JSON and XML
java, json, rest, spring, spring-mvc
Solution
I'm doing this in a current project without using a `ContentNegotiatingViewResolver`. For one method in my controller:
@RequestMapping(value = "/test", method = RequestMethod.GET)
@ResponseBody
public HttpEntity<BasicResponse> getBasicResponse() {
return new HttpEntity<BasicResponse>(new BasicResponse());
}
I can receive the following output based on the `Accept` request header.
Accept: application/xml (requires JAXB2 on the classpath)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<basicResponse>
<errors>
<message>test1</message>
<message>test2</message>
</errors>
</basicResponse>
Accept: application/json (requires Jackson on the classpath)
{
"errors" : ["test1", "test2"]
}
My response object is simple and uses normal annotations:
package org.mypackage.response;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class BasicResponse {
@XmlElementWrapper(name = "errors")
@XmlElement(name = "message")
private List<String> errors = new ArrayList<String>();
public BasicResponse() {
this.errors.add("test1");
this.errors.add("test2");
}
public List<String> getErrors() {
return errors;
}
}
The SpringSource spring-mvc-showcase project is also a helpful resource. I think they separate the conversions for different methods, but I am definitely doing this for one method.
I can't quite tell by your question...but if you're looking to serialize the output more than that, @chrylis is correct in that a custom serializer would be your next move. But everything I've ran into (which can get pretty complex, with nested objects in my response) converts perfectly to valid XML or JSON.
Problem
I want to provide one comprehensive REST API with support for both `JSON` and `XML`. The domain model is of complex type and we note that to produce friendly `JSON` and `XML` on the same model using `MappingJacksonHttpMessageConverter` and `JaxbMarshaller` respectively tends to give either readable XML or readable JSON 1). What's the best way to proceed? 1) Due to how objects such as maps, root tags and relations are modelled differently in `json` than in `xml`, the objects to serialize needs to be designed differently to get both tidy `json` and tidy `xml`. Utilities such as jaxb annotations only goes that far. I can think of a few candidates 1) Create both a json and xml controller/model ``` public class Controller { public Foo foo() { return new Foo(); } } public class XmlController extends Controller { @Override public XmlFoo foo() { return new new XmlFoo(super.foo()); } } public class JsonController extends Controller { @Override public JsonFoo foo() { return new JsonFoo(super.foo()); } } ``` Given a model object `Foo` create a `JsonFoo` and `XmlFoo` 2) Write a custom message converter I tried this and it turned out to be a bit complicated since the view must know how to resolve e.g., a `Foo` to a `JsonFoo` to be able to serialize it into a readable format. 3) Let each model object serialize itself, e.g., ``` public class Foo { public String serialize(Serializer s) { return s.serialize(this); } } ``` Based on some arbitration parameter let the controller inject the correct serializer ``` new Foo(new FooJsonSerializer()); new Foo(new FooXmlSerializer()); ```