JSON mapping
Our REST controller used JSON helper objects to map objects to JSON. First, we will start with the Products JSON helper.
ProductsJson is located at ReactiveWebStore/app/controllers/Product.scala:
object ProductsJson {
import play.api.libs.json._ import play.api.libs.json.Reads._ import play.api.libs.functional.syntax._ implicit val productWrites: Writes[Product] = (
(JsPath "id").write[Option[Long]] and (JsPath "name").write[String] and (JsPath "details").write[String] and (JsPath "price").write[BigDecimal]
)(unlift(Product.unapply))
implicit val productReads: Reads[Product] = (
(JsPath "id").readNullable[Long] and (JsPath "name").read[String] and (JsPath "details").read[String] and (JsPath "price").read[BigDecimal]
)(Product.apply _)
def toJson(products:Option[Seq[Product]]) = Json.toJson(products)
}
Basically, there are three important concepts here. First, we have productsWrites , which maps from JSON to model, and Product for writes, which is also known as deserialization. We have another mapping for serialization called productsReads, which converts objects to JSON.
As you can see, we need to map all fields existing in our model, such as ID, name, details, and price. This mapping must match proper types as well. ID mapping uses readNullable because ID is optional.
Finally, we have a function to convert from JSON to object, called toJson, which uses a generic Play framework library called JSON. Let's move for the next helper-the review.
ReviewsJson is located at ReactiveWebStore/app/controllers/Review.scala and should look something like this:
object ReviewsJson {
import play.api.libs.json._ import play.api.libs.json.Reads._ import play.api.libs.functional.syntax._ implicit val reviewWrites: Writes[Review] = (
(JsPath "id").write[Option[Long]] and (JsPath "productId").write[Option[Long]] and (JsPath "author").write[String] and (JsPath "comment").write[String]
)(unlift(Review.unapply))
implicit val reviewReads: Reads[Review] = (
(JsPath "id").readNullable[Long] and (JsPath "productId").readNullable[Long] and (JsPath "author").read[String] and (JsPath "comment").read[String]
)(Review.apply _)
def toJson(reviews:Option[Seq[Review]]) = Json.toJson(reviews)
}
Here, we have the same concepts that we saw earlier in the Products JSON helper. We have a mapping for reads and writes and a function which converts a model.Review to JSON. Let's move to the last helper, the ImageJson.
ImagesJson is located at ReactiveWebStore/app/controllers/Image.scala, which should look something like this:
object ImagesJson {
import play.api.libs.json._ import play.api.libs.json.Reads._ import play.api.libs.functional.syntax._ implicit val imagesWrites: Writes[Image] = (
(JsPath "id").write[Option[Long]] and (JsPath "productId").write[Option[Long]] and (JsPath "url").write[String]
)(unlift(Image.unapply))
implicit val imagesReads: Reads[Image] = (
(JsPath "id").readNullable[Long] and (JsPath "productId").readNullable[Long] and (JsPath "url").read[String]
)(Image.apply _)
def toJson(images:Option[Seq[Image]]) = Json.toJson(images)
}
Just as with the other two mappers, we have reads, writes, mappings, and the toJson function. We are done with mappers, so now the next step is to create the new routes.