Как читать и записывать объект Anorm с помощью нового JSON API в Play Framework 2.1-RC2?

Я пытаюсь перенести свое приложение Play 2.0.x на Play 2.1-RC2 и наткнулся на следующую проблему. В моем приложении у меня есть класс case, который выглядит так:

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

и в моем коде Play 2.0.x у меня есть объект PlayerFormat для чтения и записи экземпляров JSON этого класса, который выглядит так:

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)
      )    
  )
)

}

Вопрос в том, «как я могу в Play 2.1 прочитать необязательное (обнуляемое) свойство «id» и на основе его существования установить для атрибута playerId значение Id[Long] или NotAssigned

Кроме того, можно ли это как-то переписать, чтобы использовать начальные макросы JSON?


person Marek Radonsky    schedule 15.01.2013    source источник


Ответы (1)


Json Macro Inception здесь не лучший выбор, потому что этот случай слишком сложен. Он поддерживает только классический случай, вы не можете, например, map значения.

В этой ситуации вам нужен специальный форматер

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))

Это немного сложно, как и ваши требования;)

person Julien Lafont    schedule 15.01.2013
comment
Спасибо Жюльен, это именно то, что я искал. - person Marek Radonsky; 16.01.2013