Enterprise Java

Play! Framework Json Example

As we’ve seen in our previous example, Play! is a powerful web mvc framework.

Among other stuff, Play has support for rest clients (in its WS package), web sockets, and our subject today: json.

In this example, we’ll see how to write a Restful Web Service with Play! Framework with both scala and java languages using java 1.8.0_66, scala 2.11.6 and Play 2.4.3.

1. JSON

JSON (JavaScript Object Notation) is defined by wikipedia as “an open standard format that uses human-readable text to transmit data objects consisting of attribute–value pairs”.

In other words, we can see JSON as a key-value map, between curly braces, with each entry separated by commas, like:

{
    "some_string": "my awesome string",
    "array_key": [ "my awesome first array item",  "my awesome second array item" ],
    "some_boolean": true,
    "some_number": 1234
}

Given this first approach, let’s get dirty and write some code. Have a look at this example of how to get started with play, and then come back to write a rest API on top of it.

2. The Code

So, now we have a play application, either on scala or java, up and running. And now we’ll write some actual code.

Let’s make our model, in a package model next to controllers, and write a class Person, which will be our domain.

Person.java

package model;

public class Person {

        private final String name;
        private final int age;

        public Person(String name, int age) {
                this.name = name;
                this.age = age;
        }

        public String getName() { return name; }

        public int getAge() { return age; }

}

Person.scala

package model;

case class Person(name: String, age: Int)

As you might be guessing, a JSON representation of a Person such as Person("michael", 21) would look like:

{
    "name": "michael",
    "age": 21
}

So how do we receive and send something like this in a Play Action?

Let’s move back to our controllers package and write a PersonController

PersonController.java

package controllers;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import play.*;
import play.libs.Json;
import play.mvc.*;

import model.Person;

import java.util.LinkedList;
import java.util.List;

public class PersonController extends Controller {

	private final List repository = new LinkedList();

	public Result all() {
        ArrayNode result = Json.newArray();
        repository.forEach(p -> {
            ObjectNode node = Json.newObject();
            node.put("name", p.getName());
            node.put("age", p.getAge());
            result.add(node);
        });
        return ok(result);
    }

    @BodyParser.Of(BodyParser.Json.class)
    public Result insert() {
        JsonNode json = request().body().asJson();
        String name = json.findPath("name").textValue();
        int age = json.findPath("age").intValue();
        repository.add(new Person(name, age));
        return ok();
    }

}

PersonController.scala

package controllers

import model.Person
import play.api.libs.functional.syntax._
import play.api.libs.json._
import play.api.mvc._

import scala.collection.mutable

class PersonController extends Controller {

  val repository: mutable.MutableList[Person] = new mutable.MutableList[Person]()

  implicit val personWrites: Writes[Person] = (
      (JsPath \ "name").write[String] and
      (JsPath \ "age").write[Int]
    )(unlift(Person.unapply))
  implicit val personReads: Reads[Person] = (
      (JsPath \ "name").read[String] and
      (JsPath \ "age").read[Int]
    )(Person.apply _)

  def all = Action {
    Ok(Json.toJson(repository)).as(JSON)
  }

  def insert = Action(BodyParsers.parse.json) { request =>
    val either = request.body.validate[Person]
    either.fold(
      errors => BadRequest("invalid json person"),
      person => {
        repository.+=(person)
        Ok
      }
    )
  }

}

Here, we are defining an array of people, an action to insert a person in this array, an another one to retrieve them all.

The java controller’s json mapping is pretty straight forward. Play uses fasterxml and you can use ObjectNode as a Map implementation, and ArrayNode as a collection implementation (-ish). So there isn’t much to say about it.

The magic is going on in the scala side this time, play makes it more transparent with its Writes/Reads implementations. I defined two implicits: PersonWrites and PersonReads. The Writes defines a procedure to convert from the unapply method to JSON, and the Reads defines another one to convert from a JSON to the list of parameters of the apply method.

Now, if you check the signature of validate[-A] in the first line of our insert action, you’ll see it receives and implicit Reads. The same goes to Json.toJson, which receives an implicit Writes as parameter.

So now, we route them in our routes file in the conf directory:

routes

# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

# Home page
GET     /                           controllers.Application.index()

POST    /people                     controllers.PersonController.insert()
GET     /people                     controllers.PersonController.all()

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.versioned(path="/public", file: Asset)

3. The Test

Now we run our application and run this command in our favorite console:

curl -v --request POST --header "Content-Type: application/json" --data '{ "name": "Michael", "age": 21 }' http://localhost:9000/people

This should output some text in which should be the http response code (which should be 200). And then we run:

curl http://localhost:9000/people

And the output should look like:

[{"name":"Michael","age":21}]

4. Wrapping this up

Of course there are other ways to do this kind of things. Play’s JSON support is not the only way to provide Restful web services in a Play application, but this is a basic approach making use of it, and as you can see, it’s pretty straight forward, readable and effective.

5. Download the Code Project

This was a tutorial on one of the many many many many many ways to write a Restful web service in a play application.

Download
You can download the full source code of this example here: play-scala-example, play-java-example

Sebastian Vinci

Sebastian is a full stack programmer, who has strong experience in Java and Scala enterprise web applications. He is currently studying Computers Science in UBA (University of Buenos Aires) and working a full time job at a .com company as a Semi-Senior developer, involving architectural design, implementation and monitoring. He also worked in automating processes (such as data base backups, building, deploying and monitoring applications).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Francis
Francis
6 years ago

I am getting an error on the lines;

node.put(“name”, p.getName());
node.put(“age”, p.getAge());

The error is cannot resolve method.

What might be causing the issue?

Back to top button