Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json Writes in Play 2.1.1

I started using the Playframework recently and am implementing a site using Play 2.1.1 and Slick 1.0.0. I'm now trying to wrap my head around Json Writes as I want to return Json in one of my controllers.

I've been looking at several references on the subject (like this one and this one but can't figure out what I'm doing wrong.

I have a model looking like this:

case class AreaZipcode(  id: Int,
                     zipcode: String,
                     area: String,
                     city: String
                    )

object AreaZipcodes extends Table[AreaZipcode]("wijk_postcode") {

    implicit val areaZipcodeFormat = Json.format[AreaZipcode]

    def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
    def zipcode = column[String]("postcode", O.NotNull)
    def area = column[String]("wijk", O.NotNull)
    def city = column[String]("plaats", O.NotNull)

    def autoInc = * returning id

    def * = id ~ zipcode ~ area ~ city <> (AreaZipcode.apply _, AreaZipcode.unapply _)
}

You can see the implicit val which I'm trying to use, but when I try to return the Json in my controller by doing this:

Ok(Json.toJson(areas.map(a => Json.toJson(a))))

I'm somehow still confronted with this errormessage:

No Json deserializer found for type models.AreaZipcode. Try to implement an implicit     Writes or Format for this type. 

I've tried several other ways to implement the Writes. For instance, I've tried the following instead of the implicit val from above:

implicit object areaZipcodeFormat extends Format[AreaZipcode] {

    def writes(a: AreaZipcode): JsValue = {
      Json.obj(
        "id" -> JsObject(a.id),
        "zipcode" -> JsString(a.zipcode),
        "area" -> JsString(a.area),
        "city" -> JsString(a.city)
      )
    }
    def reads(json: JsValue): AreaZipcode = AreaZipcode(
      (json \ "id").as[Int],
      (json \ "zipcode").as[String],
      (json \ "area").as[String],
      (json \ "city").as[String]
    )

}

Can someone please point me in the right direction?

like image 251
gorow Avatar asked Dec 20 '22 04:12

gorow


1 Answers

JSON Inception to the rescue! You only need to write

import play.api.libs.json._
implicit val areaZipcodeFormat = Json.format[AreaZipcode]

That's it. No need to write your own Reads and Writes anymore, thanks to the magic of Scala 2.10 macros. (I recommend that you read Play's documentation on Working with JSON, it explains a lot.)

Edit: I didn't notice you already had the Json.format inside the AreaZipcodes object. You either need to move that line out of AreaZipcodes or import it into your current context, i.e.

import AreaZipcodes.areaZipcodeFormat
like image 151
Carsten Avatar answered Dec 22 '22 17:12

Carsten