【问题标题】:Convert Json to Joda DateTime in Play! scala 2.5在 Play 中将 Json 转换为 Joda DateTime!斯卡拉 2.5
【发布时间】:2017-03-17 07:54:12
【问题描述】:

我已阅读此 question(以及 SO 上的其他内容),但我仍然无法将 JsValue 转换为带有 Joda DateTime 的案例类。

这是我拥有的 JSON:

val json = Json.parse(
    """
    {
        "message": "Bla bla bla",
        "updated_time": "2016-09-17T12:48:12+0000"
    }
    """
)

而对应的案例类为:

import org.joda.time.DateTime
final case class FacebookPost(message: String, updated_time: DateTime)

我还添加了这个隐式 DateTime 阅读器(我也尝试了其他一些):

 implicit val readsJodaLocalDateTime = Reads[DateTime](js =>
        js.validate[String].map[DateTime](dtString => new DateTime(dtString)))

但是当我尝试将我的 json 转换为相应的案例类(json.as[FacebookPost])时,我收到了这个错误:

play.api.libs.json.JsResultException: `JsResultException(errors:List((/updated_time,List(ValidationError(List(error.expected.jodadate.format),WrappedArray(yyyy-MM-dd))))))`

我做错了什么?

【问题讨论】:

    标签: json scala datetime playframework jodatime


    【解决方案1】:

    您的问题是日期时间的格式:2016-09-17T12:48:12+0000

    默认情况下,Joda 的 DateTime 类无法自动识别您使用的格式,因此您必须使用 DateTimeFormat 提供提示。

    我们自定义Reads[DateTime]的示例:

    import play.api.libs.json._
    import play.api.libs.json.Reads._
    import play.api.libs.functional.syntax._ 
    
    val dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
    
    val customReads = Reads[DateTime](js =>
      js.validate[String].map[DateTime](dtString =>
        DateTime.parse(dtString, DateTimeFormat.forPattern(dateFormat))
      )
    )
    
    implicit val reads: Reads[FacebookPost] = (
      (__ \ "message").read[String] and
      (__ \ "updated_time").read[DateTime](customReads)
    )(FacebookPost.apply _)
    

    然后,可以执行以下操作:

    val json = Json.parse(
      """
        {
          "message": "Bla bla bla",
          "updated_time": "2016-09-17T12:48:12+0000"
        }
       """)
    
    val post = json.validate[FacebookPost] 
    // => JsSuccess(FacebookPost(Bla bla bla,2016-09-17T14:48:12.000+02:00))
    

    编辑:

    您无需从头开始创建Read[DateTime],Play 中有一个预定义的方法可以帮助您:

    object CustomReads /* or wherever you want to define it */ {
      val dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
      implicit val jodaDateReads = play.api.libs.json.Reads.jodaDateReads(dateFormat)
    }
    

    完成。只需在需要时导入,例如在模型类的伴随对象中:

    object FacebookPost {
      import utils.CustomReads._
      implicit val reads: Reads[FacebookPost] = Json.reads[FacebookPost]
    }
    

    您可以通过从导入中排除 Play 提供的隐式 Read[DateTime] 来“覆盖”它:

    import play.api.libs.json.Reads.{DefaultJodaDateReads => _, _}
    

    【讨论】:

    • 好的,它就像这样工作,但我想要一个解决方案,以便不必使用 DateTime 为每个类编写隐式读取。这应该是可能的,因为我在将 JsValue 转换为 Char 时会这样做。
    • 好的,有没有办法覆盖它们?
    • 感谢您的编辑,这似乎是一个好方法,但我仍然遇到同样的错误......
    • 如果确实与您的第一篇文章中的错误相同,那么您仍然不小心导入了 Play 的隐式 Reads[DateTime]。我加了一个minimal working example on github,也许有帮助。
    • 完美的回应,我使它与您提供的示例一起使用。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-06-07
    • 2019-02-25
    • 2016-02-14
    • 1970-01-01
    • 2012-11-15
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多