Using YAML as Response Format for Services in Spring
Recently, we were developing an iPhone application where the iPhone developer was insistent on utilizing YAML as the response format for service calls. This seemed odd given the prevalence of JSON as a response format and an already built library for parsing and handling JSON within Objective C that works with the iPhone SDK. The other advantage to JSON is there is another project that has built a JSON view resolver for converting model/domain objects into JSON. The advantage with YAML is that it inherently supports circular references and can resolve them during serialization and deserialization. While domain objects can have circular references in design, I try to keep them minimal and out of the model objects to ensure most serialization techniques work easily.
I couldn’t quickly find any YAML Spring View support so went about working through my own. Using the source of the JSON Spring View project as baseline I was quickly able to build out a baseline view handler. I say baseline because I haven’t fully unit tested the code as yet.
YamlView Class
This makes use of the jyaml library.
public class YamlView extends AbstractView {
private static final String DEFAULT_YAML_CONTENT_TYPE = "application/yaml";
public YamlView() {
super();
setContentType(DEFAULT_YAML_CONTENT_TYPE);
}
/**
* Creates a YAML String from the model values.
*/
@SuppressWarnings("unchecked")
protected final String defaultCreateYaml(Map model) {
return Yaml.dump(model);
}
/**
* Creates a Yaml String from the model values.
*/
@SuppressWarnings("unchecked")
protected String createYaml(Map model, HttpServletRequest request, HttpServletResponse response) {
return defaultCreateYaml(model);
}
@SuppressWarnings("unchecked")
@Override
protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
response.setContentType(getContentType());
writeYaml(model, request, response);
}
@SuppressWarnings("unchecked")
protected void writeYaml(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
String yaml = createYaml(model, request, response);
response.getWriter().write(yaml);
}
}
Configuration: applicationContext.xml
In one of the Spring configuration files where the web presentation layer is set.
...
...
The order is in place because this configuration file has multiple ViewResolvers. The xmlViews.xml then has the configuration:
And finally, the usage within a controller:
public class ExampleController extends AbstractCommandController {
...
@Override
protected ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object command, BindException bindException)
throws Exception {
...
String viewType = "jsonView";
if (request.getRequestURI().endsWith(".yaml")) {
viewType = "yamlView";
}
return new ModelAndView(viewType, model);
}
...
}
It really is amazing the little amount of custom code required these days to get great results.