Show Navigation

JSON Views

By Jeff Scott Brown

April 13, 2016

Tags: #json #rest

We recently published another Grails® Quickcast, brought to you in collaboration with DZone. In case you missed the first episode on Grails 3 Interceptors, you can view it here.

The latest episode introduces JSON Views, a really simple yet powerful tool supported by Grails 3 for describing the JSON response formats for REST APIs. The video is available here.

Another powerful feature supported by the tool is convention-based content negotiation.

Consider a simple domain class.

package demo

import grails.rest.Resource

@Resource(uri='/books', formats=['json'])
class Book {
    String title
    String author
}

A simple JSON view for that domain class might look like this.

// grails-app/views/book/_book.gson
import demo.Book

model {
	Book book
}

json {
   bookTitle book.title
   bookAuthor book.author
}

When a request is made to render a Book, that view will be used by default.

    $ curl http://localhost:8080/books/1.json
    {"bookTitle":"Wool","bookAuthor":"Hugh Howey"}

Grails takes into account a number of factors when attempting to resolve the view including the content type, version and locale.

The following paths are searched:

  • view_name[_LOCALE][_ACCEPT_CONTENT_TYPE][_ACCEPT_VERSION].gson (Example: show_de_hal_v1.0.gson)
  • view_name[_LOCALE][_ACCEPT_CONTENT_TYPE].gson (Example: show_de_hal.gson)
  • view_name[_LOCALE][_ACCEPT_VERSION].gson (Example: show_de_v1.0.gson)
  • view_name[_LOCALE].gson (Example: show_de.gson)
  • view_name[_ACCEPT_CONTENT_TYPE][_ACCEPT_VERSION].gson (Example: show_hal_v1.0.gson)
  • view_name[_ACCEPT_VERSION][_ACCEPT_CONTENT_TYPE].gson (Example: show_v1.0_hal.gson)
  • view_name[_ACCEPT_CONTENT_TYPE].gson (Example: show_hal.gson)
  • view_name[_ACCEPT_VERSION].gson (Example: show_v1.0.gson)
  • view_name.gson (Example: show.gson)

The content type (defined by either the ACCEPT header or file extension in the URI) is taken into account to allow different formats for the same view.

For more detail, see the official documentation.

You might also like ...