Handling and serving JSON requests
Handling a JSON request
A JSON request is an HTTP request using a valid JSON payload as request body. Its Content-Type header must specify
the text/json or application/json MIME type.
An action can retrieve the raw body content, or can ask Wisdom to convert it to an object, such as a JSON Node object in the following example:
include::{sourcedir}/controllers/json/JsonController.java[tags=hello-json]
Of course, it’s much better to use the @Body annotation:
include::{sourcedir}/controllers/json/JsonController.java[tags=hello-json-with-body]
In this example, the body is automatically mapped to a JsonNode. The @NotNull annotation manages the case where
the body is empty. A bad request result will be sent back.
A third, even better, way to receive Json content is to use a validated bean/structure instead of a JsonNode:
include::{sourcedir}/controllers/json/JsonController.java[tags=hello-json-with-body-and-bean]
The structure contains validation annotation, constraining the received data. For any non compliant content, a bad request will be returned. In addition, this way also accepts requests with other types of content (such as form input).
Serving a JSON response
In our previous examples we handled requests with a JSON body, but replied with a text/plain response. Let’s change
that to send back a valid JSON HTTP response:
include::{sourcedir}/controllers/json/JsonController.java[tags=build-json-using-json-service]
-
First, access the Wisdom Json service using the
@Requiresannotation. -
Create a new (Jackson)
ObjectNodefrom the retrieves Json service -
Just pass the created object in the
okmethod
Invoked with the {"name":"wisdom"} payload, the action returns:
{
"name" : "wisdom",
"message" : "hello wisdom"
}
However, building your own Json object can be very annoying and cumbersome. Fortunately, Wisdom builds a Json representation from an object:
include::{sourcedir}/controllers/json/JsonController.java[tags=build-json-using-mapping]
-
Define the structure you want to return
-
Pass the created object to the
okmethod and invoke thejsonmethod
Extending Json support with your own serializer and deserializer
Wisdom relies on Jackson to handle the JSON requests and responses. Despite the provided defaults serialization and de-serialization processes, you may need to extend it with your own mapping. Wisdom lets you extend Jackson by registering Jackson’s modules containing serializers and deserializers.
Your custom serializers and deserializers must be registered within a module and then registered
to the JacksonModuleRepository service (provided by Wisdom itself):
include::{sourcedir}/controllers/json/MyJsonModuleProvider.java[tags=controller]
-
Retrieve the
MyJsonModuleProviderservice -
In your constructor, build your module with a set of serializers and deserializers.
-
Registers your module into the repository
-
Don’t forget to unregister the module from the repository
JSONP
JSON with Padding (JSONP) is a communication technique to request data from a server in a different domain, something prohibited by typical web browsers because of the same-origin policy. To use JSONP, the server must be able to generate a JSONP response, and you know what ? Wisdom knows how to do that.
Basically a JSONP response is a JavaScript code fragment structure as follows: padding({the data});. The padding is
the name of the method (callback) that will be called in the JavaScript code having requested this response.
There are several ways to generate a JSONP response:
-
using the
ok(padding, json node)method -
using the Json Service
include::{sourcedir}/controllers/jsonp/JsonPController.java[tags=renderable]
The previous snippet uses the first way to get a JSONP response. It builds a JSON Node and
creates a JSONP result object. The mime type of the response is set to text/javascript. The
previous code generates callback({"foo":"bar"});.
JSONP responses can be generated from the JSON service too:
include::{sourcedir}/controllers/jsonp/JsonPController.java[tags=json]
The json.toJSONP method generates the JSONP response from the given callback name (padding) and the given content.
This approach is convenient as you can map business objects into JSON directly (as shown in the second example).
However it requires setting the JavaScript mime type explicitly.