reads play json scala playframework scala-macros

reads - Proporcionar valor implícito para singletons en la biblioteca Play Json



play json reads (2)

Para hacer eso, debería definir un objeto implícito como este:

implicit object StatusFormat extends Format[Status] { def reads(json: JsValue) = json match { case JsString("Edited") => JsSuccess(Edited) case JsString("NotEdited") => JsSuccess(NotEdited) case _ => JsError("cannot parse it") } def writes(stat: Status) = JsString(stat.toString) }

Tengo la siguiente configuración:

sealed trait Status case object Edited extends Status case object NotEdited extends Status case class Tweet(content:String, status:Status)

Quiero usar el formato Play Json, así que supongo que tengo que tener algo como esto (no quiero hacerlo en un objeto complementario):

trait JsonImpl{ implicit val TweetFormat = Json.format[Tweet] implicit val statusFormat = Json.format[Status] implicit val StatusFormat = Json.format[Edited.type] implicit val NotEditedFormat = Json.format[NotEdited.type] }

pero el compilador se queja y dice:

No implicit format for Tweet available.

También dice que no puedo usar Edited.type porque necesita aplicar y quitar funciones. ¿Que debería hacer?

Edit1:

Puedo pensar en algo como esto:

implicit object StatusFormat extends Format[Status] { def reads(json: JsValue) = (json / "type").get.as[String] match { case "" => Edited case _ => UnEdited } def writes(stat: Status) = JsObject(Seq( stat match { case Edited => "type" -> JsString("Edited") case NotEdited => "type" -> JsString("UnEdited") } )) }

pero la parte de read tiene un problema, el compilador se queja de que necesita JsonResult no Edited.type


También es posible hacerlo de forma bastante limpia con la API funcional:

import play.api.data.validation.ValidationError import play.api.libs.functional.syntax._ import play.api.libs.json._ implicit val StatusFormat: Format[Status] = Format( (__ / ''type).read[String].collect[Status](ValidationError("Unknown status")) { case "UnEdited" => NotEdited case "Edited" => Edited }, (__ / ''type).write[String].contramap { case Edited => "Edited" case NotEdited => "UnEdited" } ) implicit val TweetFormat: Format[Tweet] = Json.format[Tweet]

Encuentro esto más claro que implementar métodos de reads y writes mano, principalmente porque resalta la simetría entre la codificación y la decodificación. Es una cuestión de gusto, sin embargo.