Pergunta

I'm trying to migrate my Play 2.0.x application to Play 2.1-RC2 and stumbled upon the following problem. In my app I have a case class that looks like this:

case class Player(
  playerId: Pk[Long],
  name: Option[String],
  groupId: Long
)

and in my Play 2.0.x code I have a PlayerFormat object for reading and writing JSON instances of this class that looks like this:

object PlayerFormat extends Format[Player] {

def reads(json: JsValue): Player = Player(
    (json \ "id").asOpt[Long].map( Id(_) ).getOrElse( NotAssigned ),
    (json \ "name").asOpt[String],
    (json \ "group" \ "id").as[Long]
)

def writes(p: Player): JsValue = toJson(
  Map(
      "id" -> toJson(p.playerId.toOption),
      "name" -> toJson(p.name),
      "group" -> toJson(
          Map("id" -> p.groupId)
      )    
  )
)

}

The question is "how can I in Play 2.1 read optional (nullable) property "id" and based on its existence set the playerId attribute to either Id[Long] or NotAssigned?"

Also, can this be somehow rewritten to use the JSON inception macros?

Foi útil?

Solução

The Json Macro Inception is not a good choice here, because this case is too complex. It only supports classic case, you cannot map values for exemple.

In this situation, you need a specific formater

import play.api.libs.json._
import play.api.libs.functional.syntax._
import anorm._

implicit val playerFormat = (
    (__ \ "id").formatNullable[Long] and
    (__ \ "name").formatNullable[String] and
    (__ \ "group" \ "id").format[Long]
)((id, name, group) => Player(id.map(Id(_)).getOrElse(NotAssigned), name, group), 
  (p: Player) => (p.playerId.toOption, p.name, p.groupId))

It's a little bit complex, as your requirements are ;)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top