play jsvalue framework json scala serialization deserialization playframework-2.1

jsvalue - return json scala



¿Personalizador JodaTime personalizado utilizando la biblioteca JSON de Play Framework? (3)

Hay un serializador de DateTime predeterminado, pero usa dt.getMillis en lugar de .toString, que devolvería una cadena compatible con ISO.

Si observa la fuente , Reads.jodaDateReads ya maneja tanto los números como las cadenas usando DateTimeFormatter.forPattern . Si desea manejar la cadena ISO8601, simplemente reemplácela con ISODateTimeFormat :

implicit val jodaISODateReads: Reads[org.joda.time.DateTime] = new Reads[org.joda.time.DateTime] { import org.joda.time.DateTime val df = org.joda.time.format.ISODateTimeFormat.dateTime() def reads(json: JsValue): JsResult[DateTime] = json match { case JsNumber(d) => JsSuccess(new DateTime(d.toLong)) case JsString(s) => parseDate(s) match { case Some(d) => JsSuccess(d) case None => JsError(Seq(JsPath() -> Seq(ValidationError("validate.error.expected.date.isoformat", "ISO8601")))) } case _ => JsError(Seq(JsPath() -> Seq(ValidationError("validate.error.expected.date")))) } private def parseDate(input: String): Option[DateTime] = scala.util.control.Exception.allCatch[DateTime] opt (DateTime.parse(input, df)) }

(simplifique lo que desee, por ejemplo, elimine el manejo de números)

implicit val jodaDateWrites: Writes[org.joda.time.DateTime] = new Writes[org.joda.time.DateTime] { def writes(d: org.joda.time.DateTime): JsValue = JsString(d.toString()) }

¿Cómo implemento un deserializador / deserializador DateTime personalizado de JodaTime para JSON? Estoy inclinado a usar la biblioteca JSON de Play Framework (2.1.1). Hay un serializador de DateTime predeterminado, pero usa dt.getMillis lugar de .toString que devolvería una cadena compatible con ISO.

Escribir lecturas [T] amd Escribe [T] para las clases de casos parece bastante sencillo, pero no puedo averiguar cómo hacer lo mismo para DateTime.


Otra solución, quizás más simple, sería hacer un mapa, por ejemplo:

case class GoogleDoc(id: String, etag: String, created: LocalDateTime) object GoogleDoc { import org.joda.time.LocalDateTime import org.joda.time.format.ISODateTimeFormat implicit val googleDocReads: Reads[GoogleDoc] = ( (__ / "id").read[String] ~ (__ / "etag").read[String] ~ (__ / "createdDate").read[String].map[LocalDateTime](x => LocalDateTime.parse(x, ISODateTimeFormat.basicdDateTime())) )(GoogleDoc) }

ACTUALIZAR

Si tenía una necesidad recurrente de esta conversión, entonces podría crear su propia conversión implícita, es solo un par de líneas de código:

import org.joda.time.LocalDateTime import org.joda.time.format.ISODateTimeFormat implicit val readsJodaLocalDateTime = Reads[LocalDateTime](js => js.validate[String].map[LocalDateTime](dtString => LocalDateTime.parse(dtString, ISODateTimeFormat.basicDateTime()) ) )


Uso Play 2.3.7 y defino en el objeto complementario las lecturas / escrituras implícitas con un patrón de cadena:

case class User(username:String, birthday:org.joda.time.DateTime) object User { implicit val yourJodaDateReads = Reads.jodaDateReads("yyyy-MM-dd''T''HH:mm:ss''Z''") implicit val yourJodaDateWrites = Writes.jodaDateWrites("yyyy-MM-dd''T''HH:mm:ss''Z''") implicit val userFormat = Json.format[User] }