web-dev-qa-db-ja.com

PlayJsonでJodaDateTimeを使用する方法

Playアプリケーションを開発していて、JodaDateTimeオブジェクトをケースクラスに使用しようとしています。

package model

import org.joda.time.DateTime
import play.api.libs.json._

case class User(name: String, created: DateTime)

object User {
  implicit val yourJodaDateReads = Reads.jodaDateReads("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
  implicit val yourJodaDateWrites = Writes.jodaDateWrites("yyyy-MM-dd'T'HH:mm:ss.SSSZ'")
  implicit val userFormat = Json.format[User]

  def main(args: Array[String]) {

  val value = Json.parse("{ \"name\" : \"hello\" , \"created\" : \"2015-07-16T20:32:04.046+02:00\" }")

  println(Json.toJson(new User("user", new DateTime())))
  println(Json.fromJson(value))
 }
}

これに基づいて solution 、私はこのエラーを受け取ります:

Error:(18, -1) Play 2 Compiler: 
 /activator-1.3.2/notifier-app/app/model/Test.scala:18: ambiguous implicit    values:
 both value yourJodaDateReads in object User of type => play.api.libs.json.Reads[org.joda.time.DateTime]
    and value userFormat in object User of type => play.api.libs.json.OFormat[model.User]

Activator1.3.2とPlay2.3.​​8を使用しています。

アドバイスをいただけますか?

前もって感謝します。

更新

play.api.libs.json.Readsの暗黙的な値と競合していることを理解しています

implicit val DefaultJodaDateReads = jodaDateReads("yyyy-MM-dd") 

この問題を解決するにはどうすればよいですか?

12
Guillaume

より良い代替案を期待して、ここで私の回避策:

val dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

val jodaDateReads = Reads[DateTime](js =>
  js.validate[String].map[DateTime](dtString =>
    DateTime.parse(dtString, DateTimeFormat.forPattern(dateFormat))
  )
)

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

val userReads: Reads[User] = (
  (JsPath \ "name").read[String] and
    (JsPath \ "created").read[DateTime](jodaDateReads)
  )(User.apply _)

val userWrites: Writes[User] = (
  (JsPath \ "name").write[String] and
   (JsPath \ "created").write[DateTime](jodaDateWrites)
  )(unlift(User.unapply))

implicit val userFormat: Format[User] = Format(userReads, userWrites)
22
Guillaume

Play 2.6では、joda DateTime jsonをシリアル化/逆シリアル化する標準的な方法は、 play-json-joda ライブラリを使用することです。 ライブラリをインポートbuild.sbtを更新します。次に、次のようなjsonリーダーとjsonライターを作成します。

import play.api.libs.json.JodaWrites
implicit val dateTimeWriter: Writes[DateTime] = JodaWrites.jodaDateWrites("dd/MM/yyyy HH:mm:ss")
import play.api.libs.json.JodaReads
implicit val dateTimeJsReader = JodaReads.jodaDateReads("yyyyMMddHHmmss")
19
Moebius

この質問はしばらくの間回答されていることは知っていますが、もっと簡潔な回答を見つけました

val pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
implicit val dateFormat = Format[DateTime](Reads.jodaDateReads(pattern), Writes.jodaDateWrites(pattern))
implicit val userFormat = Json.format[User]
4
jakehschwartz
3
Vincil Bishop

Json.toJson関数とJson.fromJson関数でUser型を設定する必要があると思います。の代わりに

println(Json.toJson(new User("user", new DateTime())))
println(Json.fromJson(value))

試してください:

println(Json.toJson[User](new User("user", new DateTime())))
println(Json.fromJson[User](value))

タイプを明示的に設定すると、フレームワークは使用する読み取り/書き込みを認識します。

pdate:Userオブジェクトを関数の引数として渡し、フレームワークが実行時に型を決定するため、必ずしもJson.toJson関数の型を設定する必要はありません。ただし、Json.fromJson[User]の場合は、タイプを設定する必要があります。そうしないと、フレームワークは読み取りたいオブジェクトのタイプを認識しません。

1