About Rambabu Posa

Ram did his Masters in IS(Information Systems) from Andhra University, Vizag, India. He has 10+ years of experience in Java Ecosystem and 3+ years of experience in Scala Ecosystem. He is author of “Scala Reactive Programming” book. Apart from Java, Java EE and Scala, he is good at Spring, Hibernate, RESTful WebServices, NoSQL, BigData Hadoop Stack, Cloud, Groovy, Play Framework, Akka Toolkit, Lagom Framework, Kafka, Kubernetes, TDD, BDD,Agile and much more. He likes sharing his knowledge through writing tutorials and books.

In my previous post, we have discussed about Play Framework basics with HelloWorld example. I hope you have experimented that example and waiting for next step in this series. If not done, better to go through my previous post first at Play! Framework Hello World Example to understand Play + Scala + SBT project structure and Play Framework basics.

In this post, we are going to discuss about one of the important module of Play! Framework: Play JSON Module with some simple and useful examples.

1. Introduction

Play! Framework is a High-productivity, Moulder and REST based Modern MVC web framework. By design, it supports REST API development using JSON over HTTP protocol. JSON is a Data Transfer or Data Exchange type that is Content Type.

JSON stands for JavaScript Object Notation. If you are new to JSON data format, please go through http://json.org website to learn some basics.

To support conversion between Scala Object and JSON, Play Framework has a separate module: Play JSON Module. It is one of the important and most frequently used module of Play! Framework.

If you want to go through the Play! JSON API source code, please go refer this GitHub url: https://github.com/playframework/play-json

Play JSON library has two kinds of API: one API for Java and another for Scala. In this post, we are going to concentrate on only Play JSON Scala API.

2. Technologies used

In this post, we are going to use the following technologies:

Scala 2.12.6

Play Framework 2.6.17

Play JSON 2.6.9

SBT 1.1.5

IntelliJ IDEA

Before exploring the next steps, please try to install Java 1.8 or later version and the above mentioned software. Let us start developing our first Play Scala Web Application in the next section.

3. Play JSON API Basics

Play! Framework supports JSON API as a separate Module and its name is play-json. The complete Play JSON API was defined in play.api.libs.json package in this module. Initial versions of Play Framework has this JSON API within main core module so it should be available only for Play Framework. Later they have moved this API into a separate module so we can used it for both Play Based projects and Non-Play Based Projects.

The main goal of Play JSON API is to provide an API to support the following features:

Convert Scala Object to JSON Object

Convert JSON Object to Scala Object

Other JSON Utilities

If we want to use this Play JSON module in our project, we should add the following library dependency in our build.sbt file as shown below:

libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.9"

Like Java or Scala has Data types to represent values, Play JSON API also have the following Data Types to represent each and every JSON Data type.

JsString: It represents a Json string value.

JsNumber: It represents a Json number value.

JsBoolean: It represents a Json boolean value.

JsObject: It represents a Json object value.

JsArray: It represents a Json array value.

JsNull: It represents a Json null value.

All these Data types have a super component: JsValue and they all are organised as shown in the below diagram:

Play JSON Data Types

We will discuss about Play JSON API’s Reads, Writes and Format in the coming sections. Apart from these API, Play JSON API has few other utilities to support extra JSON functionalities like Json, JsPath etc.

3.1 Json Utilities

Like other Play JSON API, Json is also defined in play.api.libs.json package. It provides some utilities, which are mainly useful to convert to and from JsValue structures. It contains helper functions to handle JsValues.

Json.toJson(): To convert from Scala object to JsValue, we should use Json.toJson() utility as shown below:

import play.api.libs.json._
Json.toJson(HelloWorld("Json"))

Here HelloWorld is a Scala Case class, which takes a String as a parameter. When we pass this object to Json.toJson() utility, it will convert that Scala Object into JsValue as shown below:

Json.stringify(): To represent a JsValue as a String , we should use Json.stringify() utility as shown below:

Here Scala String represents our HelloWorld case class in String format. Then we are converting that Scala String object into a JsValue using Json.parse() function.

3.2 JsPath Utilities

Like other Play JSON API, JsPath is also defined in play.api.libs.json package. JsPath represents a path into a JsValue structure. Like we use XPath to traverse XML Document, we can use JsPath to traverse JSON Object. We will extensively use it in writing Play Reads, Writes and Format implicit converters.

For instance, we have the following JSON String to represent our HelloWorld case class in String format.

Then we can access “module” property or the path to the “module” property is as shown below:

JsPath \ "module"

Suppose, we have submoulde property under module property, then we can access “submodule” property as shown below:

JsPath \ "module" \ "submodule"

JsPath is basic building block to write manual Reads/Writes/Format converters. We will explore on “How to write manual converters and how to use these helper functions or utilities” in-depth in the coming examples sections.

Play JSON API has the following three different Converters to convert JsValue to Scala Value (or Scala Object) and vice versa:

READS Converter

WRITES Converter

FORMAT Converter

Let us use the following case class to explore these three converters.

HelloWorld.scala

case class HelloWorld(module:String, submodule:String)

We will discuss these converters in-detail in the coming sections with some useful examples.

4. Play JSON Reads Converter

In Play JSON API, Reads Converters are used to convert a JsValue to a Value ( in specific words, its a Scala Value or Scala Object or Scala Type). Reads is also defined as a trait in play.api.libs.json package.

Here we can also use other words instead of “convert” word. It decodes or deserialises or converts a JsValue to a Scala Value as shown in the below diagram.

Play JSON Reads Converter

So Writes converter is also know as “Deserialiser” as it deserialises a JSON type (JsValue) to a Scala Value.

We usually write Reads as implicit objects. When our program finds that Reads implicit object in scope, our program will decode that JSON into a right type.

Automatic Reads for HelloWorld type:

implicit val reads = Json.reads[HelloWorld]

This is called “JSON Automated Mapping” for Reads. We don’t need to worry about mapping each and every property of a case class with property type. If we have any specific requirement or Play Framework does NOT automatic mapping for your types, then we can use “JSON Manual Mapping” as shown below:

Here we have mapped both HelloWorld case class properties with property data type of String. As discussed in previous section, we use JsPath and “\” utilities to traverse each property.

We should specify HelloWorld.apply function to read each property one by one from the given JSON object and create an object of type HelloWorld.

5. Play JSON Writes Converter

In Play JSON API, Writes Converters are used to convert a Value ( in specific words, its a Scala Value or Scala Object or Scala Type) to a JsValue. Writes is also defined as a trait in play.api.libs.json package.

Here we can also use other words instead of “convert” word. It encodes or serialises or converts a Scala Value to a JsValue as shown in the below diagram.

Play JSON Writes Converter

So Writes converter is also know as “Serialiser” as it serialises a Scala Value into a JSON type (JsValue).

Like Reads, we usually write Writes as implicit objects. When our program finds that Writes implicit object in scope, our program will encode that Scala type into a JSON.

Automatic Writes for HelloWorld type:

implicit val writes = Json.writes[HelloWorld]

This is called “JSON Automated Mapping” for Writes. We can also write “JSON Manual Mapping” as shown below:

Here we have mapped both HelloWorld case class properties with property data type of String. We should specify HelloWorld.unapply function to extract each and every property of type HelloWorld into a JSON object. So far good, we use apply function for Reads and unapply function for Writes. What about that “unlift“? Good question!😊

Here we can observe that our HelloWorld case class contains both apply and unapply functions. As we know, HelloWorld case class contains two properties and both are of type String.

Well, apply function takes right parameters types: String, String like HelloWorld apply(String, String). However, if we observe the return type or result type of unapply function, its NOT String, String like Option<Tuple2> unapply(HelloWorld). Its returning Option of (String,String), but should be (String,String) to work Writes converter properly with unapply function. To remove this extra Option type, we use unlift function available in play.api.libs.functional.syntax package object.

I hope you understand it very well.

6. Play JSON Format Converter

In Play JSON API, Format Converters are used to convert a JsValue to a Scala Type or vice versa (that is from a Scala Type to a JsValue). In simple words, Play JSON Format converter contains both Reads and Writes converters that is Format = Reads + Writes as shown below.

Play JSON Format = Reads + Writes

In other way, we can represent this Format converter as shown below:

Play JSON Format Converter

Like Reads and Writes, Format is also defined as a trait in play.api.libs.json package.

Here we can also use other words instead of “convert” word. It encodes and decodes or serialises and deserialises or converts a Scala type to a JsValue and vice versa as shown in the below diagram.

Like Reads and Writes, we usually write Format as implicit objects. When our program finds that Format implicit object in scope, our program will encode that Scala type into a JSON or decode a JSON into a Scala type.

NOTE: In post, to define converters I have used “Value” as Scala Value. But it can be anything based on language we use it. For instance, if we use them in Java, this “Value” means “Java Value”.

That’s all about three Play Framework’s Converters or Combinators. Play Framework source code defined them as Macros.

7. Play JSON Scala HelloWorld Example

So far, we have discussed theory enough theory about Play JSON Module. Its time to start developing a simple and basic HelloWorld example using Play Framework, Play JSON Module and Scala.

We are going to use IntelliJ IDE and SBT build tool to develop this application. If you are using IntelliJ IDE Ultimate Edition, first please create a Play Framework web application using IDE. If you are using IntelliJ IDE CE (Community Edition), please download the Play Scala Starter project from the following Lightbend’s Play Framework Examples GitHub location:https://github.com/playframework/play-scala-starter-example

I have renamed this project as “PlayJSONScalaHelloWorldExample”, imported into IntelliJ IDE and deleted all files.

Then please continue the following steps to develop our HelloWorld application:

Add SBT Play Framework plugin to “plugins.sbt” file as shown below:

plugins.sbt

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.17")

In my previous two posts, I was using Play Framework SBT plugin version “2.6.13”. Please follow Play Framework blog at https://blog.playframework.com for regular release updates.

Here we have mapped “/hello/:module” URI to HelloWorldJSONController.hello function. That means when User accesses our application with something like http://localhost:9000/hello/json, that request is served by this hello function.

Like previous examples, we have developed an example by extending InjectedController and using @Inject annotation

Unlike previous examples, hello Action or function is NOT using any Scala View Template to serve response back to the End User. It’s directly sending HelloWorld Case class as Play Results to End User as shown below:

The return type of toJson function is JsValue. As discussed, JsValue is super type of all Play JSON API and is generic JSON value type.

We will try to develop another Endpoint for same functionality using Scala View Template soon.

7.1 Test Play JSON HelloWorld Example

In this section, we will test Play JSON HelloWorld example developed in the previous section. Please do the following steps one by one:

To up and run our application, please execute the following sbt command

$cd PlayJSONScalaHelloWorldExample
$sbt run

Access http://localhost:9000/hello/json url from web browser as shown below and observe the result

Test Play JOSN + Scala HelloWorld Example with Browser

7.2 Play JSON HelloWorld without Json.toJson

If we observe our previous Play JSON HelloWorld Example, our HelloWorldJSONController controller converts HelloWorld Scala object to JsValue using Json.toJson() utility and sends thats response back to End User to render it on a Web Browser. It was working fine.

What will happen if we send that HelloWorld Scala object as is? Please do the following changes to our controller:

Here we just removed the Json.toJson() function call in hello Action. Please access the same url http://localhost:9000/hello/json from web browser as shown below and observe the results:

Play JSON + Scala HelloWorld Error Scenario

Here if we can observe the error message, it clearly says that we need to develop a “Writeable[models.HelloWorld]”. We will discuss about Writeable in a separate post.

7.3 Play JSON HelloWorld Example with View Template

If we observe our main Play JSON HelloWorld Example, we can say that our Controller has not used Scala View Template to render the response. It just converts our Data model into JSON and sends that JSON to the End user directly.

In this section, we will do the same functionality by using Scala View Template. Please do the following steps to experiment this scenario:

Please access the same url http://localhost:9000/hello/view/json from web browser as shown below and observe the results:

Play JSON + Scala HelloWorld with Scala Template

That’s it about Play JSON + Scala HelloWorld Basic Example. Let us explore Play Framework JSON module few more details with one more example in the coming section.

8. Play JSON Scala Complex Example

In previous section, we have developed a basic, simple and easy to understand Play JSON HelloWorld example using Writes converter only. Here we are going to develop another example to explore all 3 converters: Reads, Writes and Format using Play Framework, Play JSON Module and Scala.

We are going to use IntelliJ IDE and SBT build tool to develop this application. If you are using IntelliJ IDE Ultimate Edition, first please create a Play Framework web application using IDE. If you are using IntelliJ IDE CE (Community Edition), please download the Play Scala Starter project from the following Lightbend’s Play Framework Examples GitHub location:https://github.com/playframework/play-scala-starter-example

I have renamed this project as “PlayJSONScalaBooksExample”, imported into IntelliJ IDE and deleted all files.

Then please continue the following steps to develop our HelloWorld application:

Here we have hardcoded couple of Books list for out testing purpose. When we discuss about “Play Framework + Scala + Database Example”, we will try to store this data some where in Relational Database or NoSQL Data store.

First point, we should understand is implicit request object. To understand this, we should discuss the following two questions:

What does it really contain?

Why do we need this?

Answer to first question is that it contains User Request information like body or header. In our example, when User sent a POST request with Book information (see screenshots to understand it very well), this request implicit object’s body contains that Book information.

The Answer to the second question is that if we want to retrieve that Book information form User Request body, we should use this implicit request object. We can use it without implicit object also as shown below:

In our case, it works fine (test it by updating this example). However, Play Framework team (Lightbend) recommends to use this request object as implicit so that if any of User components or Play Framework components needs it as implicit, our application does NOT complain any errors.

In our example, we have retrieved our Book information using request.body.as[Book] code.

Please access http://localhost:9000/books url to observe the available Books list from our BookStore as shown below:

Get all Books available in BookStore

Please access http://localhost:9000/books url with Book details to add new Book to existing Book list of our BookStore as shown below:

Add new Book to our BookStore

Please access http://localhost:9000/books/ISBN04 url to observe the details of our newly added Book from our BookStore as shown below:

Get New Book Details

9. Conclusion

One of the best features of Play! Framework is that it supports REST API by design. It has a separate JSON module “play-son” to develop RESTful Web services easily. As its an independent module, we can use it not only in Play Framework, in any other web frameworks or standalone applications too.

Play JSON API defines required JSON types and some utilities to take care of supporting JSON API in Play Framework. It has 3 combinators: Reads, Writes and Format to ease the process of converting Scala Values to JsValues and vice versa.

We have developed two simple and easy to understand Play JSON examples in Scala language using SBT build tool. Please go through the Play JSON module source code to understand this API in-depth.

10. References

If you are interested to learn more details about Play Framework, Play JSON, Scala Language and SBT tool, please refer the following important websites:

Newsletter

Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

Email address:

Receive Java & Developer job alerts in your Area

Leave this field empty if you're human:

Join Us

With 1,240,600 monthly unique visitors and over 500 authors we are placed among the top Java related sites around. Constantly being on the lookout for partners; we encourage you to join us. So If you have a blog with unique and interesting content then you should check out our JCG partners program. You can also be a guest writer for Java Code Geeks and hone your writing skills!

Disclaimer

All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners. Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. Examples Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.