17

JSON 用のカスタム JodaTime の DateTime シリアライザー/デシリアライザーを実装するにはどうすればよいですか? Play フレームワークの JSON ライブラリ (2.1.1) を使用する傾向があります。デフォルトの DateTime シリアライザがありますが、dt.getMillis代わりに.toStringwhich を使用して ISO 準拠の文字列を返します。

ケース クラスの Reads[T] と Writes[T] の記述はかなり簡単に思えますが、DateTime に対して同じことを行う方法がわかりません。

4

3 に答える 3

25

デフォルトの DateTime シリアライザーがありますが、ISO 準拠の文字列を返す .toString の代わりに dt.getMillis を使用します。

ソースを見ると、 はReads.jodaDateReadsすでに を使用して数値と文字列の両方を処理していますDateTimeFormatter.forPattern。ISO8601 文字列を処理する場合は、次のように置き換えます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))

  }

(必要に応じて単純化します。たとえば、番号の処理を削除します)

  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())
  }
于 2013-08-16T06:11:45.773 に答える
19

私は Play 2.3.7 を使用し、コンパニオン オブジェクトで暗黙的な読み取り/書き込みを文字列パターンで定義します。

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]
}
于 2015-02-18T15:01:22.887 に答える