Using JSON With Play and Scala
Using JSON with Java's Play framework and Scala is a natural fit. Read on to find out how you can enable and use JSON in your next Play project.
Join the DZone community and get the full member experience.
Join For FreeOnce getting your hands into typing scala code using Play, the first thing that comes to mind is JSON.
Without a doubt, JSON is one of the most basic components of web applications. REST APIs use JSON, your angular app has to consume JSON... the list goes on.
If you are lazy like me, you expect that it is sufficient to just pass back Scala objects through your controller or specify a Scala class as an argument to your controller. Somehow, things don’t get far from that; however, some adjustments have to be done.
The first step is to specify the JSON module
libraryDependencies += json
The JSON library is pretty similar to the org.json library for java but with extra capabilities. The types we have out of the box are JsString
, JsNumber
, JsBoolean
, JsObject
, JsArray
, and JsNull
.
However, the key functionality comes from the reads and writes converters, which can be used to marshal or unmarshal our data structures.
Suppose we have a class called User
:
case class User(id:Option[Long],email:String,firstName:String,lastName:String)
We want to use this class to pass data to our controllers or use it as a response once our action has finished.
Thus, we need to create a Reader and writer for the User
object.
implicit val userWrites = new Writes[User] {
def writes(user: User) = Json.obj(
"id" -> user.id,
"email" -> user.email,
"firstName" -> user.firstName,
"lastName" -> user.lastName
)
}
implicit val userReads: Reads[User] = (
(__ \ "id").readNullable[Long] and
(__ \ "email").read[String] and
(__ \ "firstName").read[String] and
(__ \ "lastName").read[String]
)(User.apply _)
Most probably, you’ve noticed that the id
is optional. We do this in order to be able to either pass the id
of the user or not.
Now, let’s put them together in a controller.
package controllers
import javax.inject.Inject
import com.google.inject.Singleton
import play.api.libs.json._
import play.api.mvc.{Action, Controller}
import play.api.libs.functional.syntax._
/**
* Created by gkatzioura on 4/26/17.
*/
case class User(id:Option[Long],email:String,firstName:String,lastName:String)
@Singleton
class UserController @Inject() extends Controller {
def all = Action { implicit request =>
val users = Seq(
User(Option(1L),"gkazoura@example.com","Emmanouil","Gkatziouras"),
User(Option(2L),"john@doe.com","John","Doe"),
User(Option(3L),"john2@doe.com","John2","Doe2")
)
Ok(Json.toJson(users))
}
def greet = Action
def add = Action { implicit request =>
val user = Json.fromJson[User](request.body.asJson.get).get
val newUser = User(Option(4L),user.email,user.firstName,user.lastName)
Ok(Json.toJson(newUser))
}
implicit val userWrites = new Writes[User] {
def writes(user: User) = Json.obj(
"id" -> user.id,
"email" -> user.email,
"firstName" -> user.firstName,
"lastName" -> user.lastName
)
}
implicit val userReads: Reads[User] = (
(__ \ "id").readNullable[Long] and
(__ \ "email").read[String] and
(__ \ "firstName").read[String] and
(__ \ "lastName").read[String]
)(User.apply _)
}
And also the roots configuration:
GET /user/ controllers.UserController.all
POST /user/ controllers.UserController.add
As we can see, the all
method returns a list of user objects in JSON, format while the add
method is supposed to persist a user object and assign an id
to it.
Let’s do a curl request and check our results
curl http://localhost:9000/user/
....
[{"id":1,"email":"gkazoura@example.com","firstName":"Emmanouil","lastName":"Gkatziouras"},{"id":2,"email":"john@doe.com","firstName":"John","lastName":"Doe"},{"id":3,"email":"john2@doe.com","firstName":"John2","lastName":"Doe2"}]
curl -H "Content-Type: application/json" -X POST -d '{"email":"emmanouil@egkatzioura.com","firstName":"Emmanouil","lastName":"Gkatziouras"}' http://localhost:9000/user/
...
{"id":4,"email":"emmanouil@egkatzioura.com","firstName":"Emmanouil","lastName":"Gkatziouras"}
So, we didn’t get into any special JSON handling or reading. Instead, we used only objects.
That’s it! Now, you are ready for more JSON-related action!
Published at DZone with permission of Emmanouil Gkatziouras, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments