Play 2.6中的Joda DateTime格式无效

时间:2017-10-16 07:11:49

标签: json scala datetime playframework jodatime

尝试将我的代码迁移到2.6 一切都很好,除了DateTime类型的格式。

作为迁移的一部分,我确实将play-json-joda添加为依赖项。

但是,这样的事情:

case class GeoArea(id: Option[Int] = None,
                   continentId: Option[Int] = None,
                   countryId: Option[Int] = None,
                   code: String,
                   name: String,
                   discr: Discriminator.Value,
                   createdAt: DateTime = DateTime.now,
                   updatedAt: DateTime = DateTime.now,
                   deletedAt: Option[DateTime] = None,
                   createdBy: Option[String] = None,
                   updatedBy: Option[String] = None)

将格式对象定义为:

implicit lazy val geoAreaFormat: Format[GeoArea] = Json.format[GeoArea]

我收到错误:

  

没有play.api.libs.json.Format的实例可供使用   org.joda.time.DateTime,org.joda.time.DateTime,   隐式作用域中的scala.Option [org.joda.time.DateTime](提示:if   在同一个文件中声明,确保它之前已声明)[错误]
  隐式lazy val geoAreaFormat:格式[GeoArea] =   Json.format [的GEOarea]

我错过了什么?我还需要在范围内解决这个问题吗?

我的导入如下:

import driver.PGDriver.api._
import org.joda.time.DateTime
import play.api.libs.json._
import slick.lifted.Tag
import model.GeoAreas.Discriminator
import converters.{JsonEnumeration, SlickEnumeration}

他们在迁移期间并没有改变,但是这些都足以让一切工作。

3 个答案:

答案 0 :(得分:6)

在你的build.sbt中添加:

libraryDependencies += "com.typesafe.play" % "play-json-joda_2.12" % "2.6.0"

然后在您的模型文件中导入:

import play.api.libs.json.JodaWrites._
import play.api.libs.json.JodaReads._

答案 1 :(得分:0)

我遇到了这种不便,转移到了新的图书馆。您可以通过基于新默认值创建隐式格式来解决此问题。

implicit val dateFormat = new OFormat[DateTime] {
    override def reads(json: JsValue): JsResult[DateTime] = JodaReads.DefaultJodaDateTimeReads.reads(json)
    override def writes(o: DateTime): JsValue = JodaWrites.JodaDateTimeWrites.writes(o)
}

请注意,上述内容不包括使用epoch millis的旧默认写入。为确保您的迁移不会破坏现有功能,您可能希望保留旧的默认值:

implicit val dateFormatDefault = new Format[DateTime] {
    override def reads(json: JsValue): JsResult[DateTime] = JodaReads.DefaultJodaDateTimeReads.reads(json)
    override def writes(o: DateTime): JsValue = JodaDateTimeNumberWrites.writes(o)
}

这是因为play-json中的旧默认值使用了millis(https://github.com/playframework/play-json/blob/master/play-json/jvm/src/main/scala/play/api/libs/json/EnvWrites.scala#L326-L328):

@deprecated("Include play-json-joda as a dependency and use JodaWrites.JodaDateNumberWrites", "2.6.0")
object DefaultJodaDateWrites extends Writes[DateTime] {
    def writes(d: DateTime): JsValue = JsNumber(d.getMillis)
}

新默认值使用ISO8601(https://github.com/playframework/play-json/blob/b4f812df628787e2d83131ceafbecb0d6d769704/play-json-joda/src/main/scala/play/api/libs/json/JodaWrites.scala#L33-L35):

/**
 * Default Serializer LocalDate -> JsString(ISO8601 format (yyyy-MM-dd))
 */
implicit object JodaDateTimeWrites extends Writes[DateTime] {
   def writes(d: DateTime): JsValue = JsString(d.toString)
}

答案 2 :(得分:0)

您应该使用nscala-time时间,这是Joda

的包装

然后,对于Json格式化程序,您可以创建此对象

package formatters

import org.joda.time.{DateTime, DateTimeZone}
import org.joda.time.format.ISODateTimeFormat
import play.api.libs.json.{JsString, JsSuccess, JsValue, Format}

object DateTimeFormatter {
  private lazy val ISODateTimeFormatter = ISODateTimeFormat.dateTime.withZone(DateTimeZone.UTC)
  private lazy val ISODateTimeParser = ISODateTimeFormat.dateTimeParser

  implicit val dateTimeFormatter = new Format[DateTime] {
    def reads(j: JsValue) = JsSuccess(ISODateTimeParser.parseDateTime(j.as[String]))
    def writes(o: DateTime): JsValue = JsString(ISODateTimeFormatter.print(o))
  }
}

并在您的伴侣对象中

object GeoArea {
  import formatters.DateTimeFormatter._
  implicit val geoAreaFormat = Json.format[GeoArea]
}