This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 15.14, “How to write a GET request web service with the Scala Play Framework.”
Problem
You want to create a GET
request web service using the Play Framework, such as returning a JSON string when the web service URI is accessed.
Solution
When working with RESTful web services, you’ll typically be converting between one or more model objects and their JSON representation.
To demonstrate how a GET
request might be used to return the JSON representation of an object, create a new Play project with the play new
command:
$ play new WebServiceDemo
Respond to the prompts to create a new Scala application, and then move into the WebServiceDemo directory that’s created.
Next, assume that you want to create a web service to return an instance of a Stock
when a client makes a GET
request at the /getStock URI. To do this, first add this line to your conf/routes file:
GET /getStock controllers.Application.getStock
Next, create a method named getStock
in the default Application
controller (apps/controllers/Application.scala), and have it return a JSON representation of a Stock
object:
package controllers import play.api._ import play.api.mvc._ import play.api.libs.json._ import models.Stock object Application extends Controller { def index = Action { Ok(views.html.index("Your new application is ready.")) } def getStock = Action { val stock = Stock("GOOG", 650.0) Ok(Json.toJson(stock)) } }
That code uses the Play Json.toJson
method. Although the code looks like you can create Stock
as a simple case
class, attempting to use only a case
class will result in this error when you access the /getStock URI:
No Json deserializer found for type models.Stock. Try to implement an implicit Writes or Format for this type.
To get this controller code to work, you need to create an instance of a Format
object to convert between the Stock
model object and its JSON representation. To do this, create a model file named Stock.scala in the app/models directory of your project. (Create the directory if it doesn’t exist.)
In that file, define the Stock
case class, and then implement a play.api.libs.json.Format object. In that object, define a reads
method to convert from a JSON string to a Stock
object and a writes
method to convert from a Stock
object to a JSON string:
package models case class Stock(symbol: String, price: Double) object Stock { import play.api.libs.json._ implicit object StockFormat extends Format[Stock] { // convert from JSON string to a Stock object (de-serializing from JSON) def reads(json: JsValue): JsResult[Stock] = { val symbol = (json \ "symbol").as[String] val price = (json \ "price").as[Double] JsSuccess(Stock(symbol, price)) } // convert from Stock object to JSON (serializing to JSON) def writes(s: Stock): JsValue = { // JsObject requires Seq[(String, play.api.libs.json.JsValue)] val stockAsList = Seq("symbol" -> JsString(s.symbol), "price" -> JsNumber(s.price)) JsObject(stockAsList) } } }
The comments in that code help to explain how the reads
and writes
methods work.
With this code in place, you can now access the getStock
web service. If you haven’t already done so, start the Play console from within the root directory of your project, then issue the run
command:
$ play [WebServiceDemo] $ run 8080
Play runs on port 9000 by default, but this collides with other services on my system, so I run it on port 8080, as shown. Assuming that you’re running on port 8080, access the http://localhost:8080/getStock URL from a web browser. You should see this result in the browser:
{"symbol":"GOOG","price":650.0}
Discussion
When converting from a Stock
object to its JSON representation, the writes
method of your Format
object is implicitly used in this line of code:
Json.toJson(stock)
Although there are other approaches to converting between objects and their JSON representation, implementing the reads
and writes
methods of a Format
object provides a straightforward means for this serialization and deserialization process.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |