Ofter we need to create RESTful API to READ data for existed domain objects with easy manipulation of fields in it. For example, we do not need to see in API result fields like ‘id’, ‘lastUpdated’, ‘createdBy’, collections, references and any other fields. Also we want to have easy way to change field name. For example, instead of ‘image’ you want ‘imageUrl’ because we need to put URL link there. And of course, we want to make different manipulations with fields, like put full URL or calculate whether shop is working now or anything else.
Of course, we can do it by simple code like
But when you have more then 20 fields in object and need to send complex structures, like send ‘address’ and ‘contact’ references but do not send ‘currentLocation’ and you have more then 10 of such objects – It became a nightmare! Support is even worst!
So, to solve this problem we create rather simple (at least when looking now on it) solution.
First define in UrlMapping something like:
So all READ API calls will be
‘/appName/api/users’ or ‘/appName/api/venues?format=json&max=10&offset=10′
In ‘ApiJsonRestController’ we need to get from domainInPlural real domain class name (through a simple mapping or complicated rule – up to you) and just send it to response:
In the result you will get list of domain instances with all fields – very Ugly.
Now is the most interesting part.
We need to override default Grails DomainClassMarshaller, so that during object rendering ours was used instead
It is a copy of DomainClassMarshaller with several modifications:
- We control whether to define id for object by protected needToDefineId()
- We control object id itself by protected getObjectIdentifier()
- processAdditionalFields() allow to put any fields you want which are not in domain
- We control fields to skip and alternative field name via protected methods getSkippedFields() and getAlternativeName(String originalName)
- We controll how to display references to other domains and collections via processSpecificFields()
So for each object where we have specific fields to skip and alternative name or some rules to display fields we need to create an extended class:
You can try to play with it, but once it is done you have no any problem with support. New fields added automatically, if you change field name it will be changed everywhere: in places where domain object rendered itself and in embedded object.
And do not forget to register your Marshallers!!! We do it in BootStrap.groovy: