I know there is a HalJsonRenderer but i wonder if there would be a way to have something like the JSON converter in order to be able to do something like:
render MyObject as HAL
That "as" operator ... how it works?
It's a bit more clear what's happening with render ... as JSON
if you add in the optional parentheses:
render(foo as JSON)
The render method has a few overloads and one of them accepts JSON, so the tricky part is foo as JSON
.
Groovy makes it straightforward to overload operators by pairing every operator with a method that actually does the work. The ==
operator is implemented by calling the equals
method (or compareTo
if the class implements Comparable
, the <<
operator calls leftShift
, etc. This archived page has a good table of operators and their corresponding methods (the Groovy site was significantly overhauled recently and this page seems to have been lost in the shuffle).
as
isn't technically an operator, but it's treated similarly. If you add an asType
method, it will be invoked to give the class an opportunity to convert itself to the requested type:
Object asType(Class c) { ... }
The way that Grails wires up as JSON
and as XML
is rather convoluted, but the important part involves adding an asType
method to all controllers (in addition to render
, redirect
, getParams
(and the corresponding params
property), etc.) This method then does the conversion to JSON or XML, or does a traditional cast/conversion if the target class isn't JSON or XML.
I think it would be more work than it's worth to support this directly, so if it were me I'd create a method in a service that does the work of converting supported types to HAL and render that, something like
class SomeService {
String asHal(foo) {
...
}
}
and then you can call it from your controllers:
class SomeController {
def someService
def anAction() {
...
def foo = ...
render someService.asHal(foo)
}
}
That's not quite as convenient as render as HAL
, but it's not much more work and has the benefit of being less magical.
To support render foo as HAL
you would need to add an asType
method to whatever class foo
is, or do something similar to what Grails does for JSON and XML. Adding an asType
method is probably impractical, especially if you want to support multiple types, and more so if those types are pre-existing classes like ArrayList. You could implement the org.codehaus.groovy.grails.web.converters.Converter
interface like the JSON and XML classes do (looking at the support code, you actually need to extend org.codehaus.groovy.grails.web.converters.AbstractConverter
), and create the associated support classes that would do the conversion (this was all designed to be extensible, although I don't think I've seen anyone do it). That would be interesting and probably a good learning experience, but as I said - way more work than it's worth given how simple the more direct implementation is.