0
votes

Hi there i found several questions like mine here on stackoverflow but none of the provided solutions seem to work for me.

I`m testing the playframework (2.2.2) and trying to figure out how to generate a json Format for a Sequence of objects.

case class Captain(
    val name: String,
    val secondname: String,
    val surname: String
)

So in my Controller i have the following Action:

def captains= Action {
    Ok(getCaptains).as("application/json")
  }

and the following method:

def getCaptains= {

    val seq = Seq[Captain](new Captain("james", "tiberius", "kirk"), new Captain("jean", "luc", "picard"))
    val jsonOutput =  Json.toJson(seq).as(Seq[Captain] _)
  }

Of course this triggers: "No Json serializer found for type Seq[models.Captain]. Try to implement an implicit Writes or Format for this type."

So following the play documentation and several threads here and around the web i used an

object Cpatain {

}

And within the object i tried the following solutions:

Writer approaches:

1:

implicit def writes(cap: Captain): JsValue = {
    val capSeq = Seq(
      "name" -> JsString(cap.name),
      "secondname" -> JsString(cap.secondname),
      "surname" -> JsString(cap.surname)
    )
    JsObject(capSeq)
  }

2:

implicit val CaptainWrites = new Writes[Captain] {
    def writes(cap: Captain): JsValue = {
      Json.obj(
        "name" -> cap.name,
        "secondname" -> cap.secondname,
        "surname" -> cap.surname
      )
    }
  }

Reader approaches:

1:

implicit val regReads: Reads[Captain] = (__ \ "captains").read(
    (__ \ "name").read[String] and
      (__ \ "secondname").read[String] and
      (__ \ "surname").read[String]
      tupled
  ) map Captain.apply _

2:

 implicit val CaptainReads =
  (JsPath \ "captains").read(
    (JsPath \ "name").read[String] and
      (JsPath \ "secondname").read[String] and
      (JsPath \ "surname").read[String]
      tupled
  )

And also:

  implicit object captainFormat extends Format[Captain] {

    def writes(cap: Captain): JsValue = {
      Json.obj(
        "name" -> JsString(cap.name),
        "secondname" -> JsString(cap.secondname),
        "surname" -> JsString(cap.surname)
      )
    }
    def reads(json: JsValue): Captain= Captain(
      (json \ "name").as[String],
      (json \ "secondname").as[String],
      (json \ "surname").as[String]
    )
  }

But in either way i result in: "type mismatch; found : Seq[models.Captain] => Seq[models.Captain] required: play.api.libs.json.Reads[?]"

This is also mentioned in: type mismatch error when creating Reads for Play 2.1

and

Json Writes in Play 2.1.1

But as you can see i allready tried the provided solutions without success.

So it seems i`m missing somesthing. I would appreciate any help!!

1

1 Answers

-1
votes

So i managed to get it running by using:

  implicit val capReads: Reads[Captain] = (
    (__ \ "name").read[String] ~
    (__ \ "secondname").read[String] ~
    (__ \ "surname").read[String]

    )(Captain.apply _)

  implicit def writes(cap: Captain): JsValue = {
    Json.obj(
      "name" -> JsString(cap.name),
      "secondname" -> JsString(cap.surname),
      "surname" -> JsString(cap.surname2)
    )
  }