【问题标题】:scala play 2.1.1 json functional syntax mapping data to a different formatscala play 2.1.1 json函数语法映射数据到不同的格式
【发布时间】:2013-08-23 16:06:27
【问题描述】:

我正在尝试使用函数式语法编写自定义 json 序列化程序,但我似乎找不到解决此特定问题的正确方法。我有几个 joda DateTime 对象,我想以特定格式为使用它的 UI 编写它们。谁能告诉我哪里出错了?

这是我目前正在处理的案例类,没有什么特别的。

case class Banner(
  id: Int = 0,
  ownerId: Int = 0,
  licenseeId: Option[Int] = None,
  statusColor: Option[String] = None,
  content: Option[String] = None,
  displayStart: DateTime = new DateTime(),
  displayEnd: DateTime = new DateTime(),
  created: DateTime = new DateTime(),
  updated: DateTime = new DateTime()
)

这些是我对序列化程序对象的导入。

import play.api.libs.json._
import play.api.libs.functional.syntax._
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat

首先,joda DateTime 隐式转换为 long 就可以了,因此如果这就是我想要的,那么宏扩展器可以很好地工作。

object MySerializers {
  implicit val writesBanner = Json.writes[Banner]
}

我需要将 displayStart 和 displayEnd 对象转换为特定的字符串格式,而不是 long 值。这就是我试图做的。

object MySerializers {
  val userDateFormatter = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm a")

  implicit val writesBanner = (
    (__ \ "id").write[Int] and
    (__ \ "ownerId").write[Int] and
    (__ \ "licenseeId").write[Int] and
    (__ \ "statusColor").writeNullable[String] and
    (__ \ "content").writeNullable[String] and
    (__ \ "displayStart").write[DateTime].inmap[String](dt => userDateFormatter.print(dt)) and
    (__ \ "displayEnd").write[DateTime].inmap[String](dt => userDateFormatter.print(dt)) and
    (__ \ "created").write[DateTime] and
    (__ \ "updated").write[DateTime]
  )(unlift(Banner.unapply))
}

但是编译器对此并不满意,所以我似乎不明白使用 inmap 函数的正确方法。

could not find implicit value for parameter fu: 
play.api.libs.functional.InvariantFunctor[play.api.libs.json.OWrites]
[error]     (__ \ "displayStart").write[DateTime].inmap[String](dt =>     
userDateFormatter.print(dt)) and
[error]                                ^

非常感谢任何建议。

【问题讨论】:

    标签: json scala playframework functional-programming playframework-2.1


    【解决方案1】:

    我设法弄清楚了这一点,我使用了错误类型的仿函数映射操作,并且我使用的类型倒退了。以下是使用更好的函数式语法的工作读/写实现。

    implicit val writesBanner = (
        (__ \ "id").write[Int] and
        (__ \ "ownerId").write[Int] and
        (__ \ "licenseeId").writeNullable[Int] and
        (__ \ "statusColor").writeNullable[String] and
        (__ \ "content").writeNullable[String] and
        (__ \ "displayStart").write[String].contramap[DateTime](dt => userDateFormatter.print(dt)) and
        (__ \ "displayEnd").write[String].contramap[DateTime](dt => userDateFormatter.print(dt)) and
        (__ \ "created").write[DateTime] and
        (__ \ "updated").write[DateTime]
      )(unlift(Banner.unapply))
    
    implicit val readsBanner = (
        (__ \ "id").read[Int] and
        (__ \ "ownerId").read[Int] and
        (__ \ "licenseeId").readNullable[Int] and
        (__ \ "statusColor").readNullable[String] and
        (__ \ "content").readNullable[String] and
        (__ \ "displayStart").read[String].fmap[DateTime](dt => DateTime.parse(dt, userDateFormatter)) and
        (__ \ "displayEnd").read[String].fmap[DateTime](dt => DateTime.parse(dt, userDateFormatter)) and
        (__ \ "created").read[DateTime] and
        (__ \ "updated").read[DateTime]
      )(Banner)
    

    【讨论】:

      【解决方案2】:

      我绝对不是这方面的专家,但我很确定您使用 inmap 的方式是您使用 contramap/fmap 的组合。

      即:

      implicit val formatBanner = (
      <truncated>
          (__ \ "displayStart").format[String].inmap(DateTime.parse(_, userDateFormatter), userDateFormatter.print(_)) and
      <truncated>
        )(Banner.apply, unlift(Banner.unapply))
      

      【讨论】:

        猜你喜欢
        • 2011-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-29
        相关资源
        最近更新 更多