使用组合器将Scala对象转换为Json Formatter

时间:2013-05-07 10:13:56

标签: json scala playframework playframework-2.1

我在Scala documentation

之后实现了一个类
case class Creature(
  name: String, 
  isDead: Boolean, 
  weight: Float,
  dob: java.sql.Date
)

import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val creatureFormat = (
  (__ \ "name").format[String] and
  (__ \ "isDead").format[Boolean] and
  (__ \ "weight").format[Float] and
  (__ \ "dob").format[java.sql.Date]
)(Creature.apply, unlift(Creature.unapply))

然后我像这样Json.toJson(Creature("John Doe", false, 100.0, new java.sql.Date(1363456800000)))调用json包装器并期望看到像 {“name”:“John Doe”,“isDead”的输出:false,“weight”:100.0,“dob “:”2013-03-17“} 。相反,我得到的输出像 {“name”:“John Doe”,“isDead”:false,“weight”:100.0,“dob”: 1363456800000 }

请注意,在数据库中,我可以看到dob为2013-03-17。

3 个答案:

答案 0 :(得分:1)

以下是我解决问题的方法(我明确定义了应用取消应用方法)

val sdf = new java.text.SimpleDateFormat("yyyy-MM-dd")
implicit val creatureFormat = (
  (__ \ "name").format[String] and
  (__ \ "isDead").format[Boolean] and
  (__ \ "weight").format[Float] and
  (__ \ "dob").format[String])
    (((name, isDead, weight, dob) => Creature(name, isDead, weight, new java.sql.Date(sdf.parse(dob).getTime()))),
    unlift((cr: Creature) => Some(cr.name, cr.isDead, cr.weight, sdf.format(cr.dob))))

我不知道是否有更好的解决方案。

更新

最后,我为java.sql.Date实现了一个格式化程序

import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.data.validation.ValidationError
import play.api.libs.json.{ Json => PlayJson, _ }

case class Creature(
  name: String, 
  isDead: Boolean, 
  weight: Float,
  dob: java.sql.Date
)

implicit val sqlDateWrite = new Format[SqlDate] {
  def reads(json: JsValue) = json match {
    case JsString(d) => {
      val theDate = new SqlDate(sdf.parse(d).getTime)
      if (d.matches(sdfPattern) && theDate.compareTo(new Date(0)) > 0) JsSuccess(new SqlDate(sdf.parse(d).getTime))
      else JsError(Seq(JsPath() -> Seq(ValidationError("validate.error.expected.date.in.format(dd-MM-yyyy)"))))
    }
    case _ => JsError(Seq(JsPath() -> Seq(ValidationError("validate.error.expected.date.in.String"))))
  }

  def writes(sd: SqlDate): JsValue = JsString(sdf.format(sd))
}

implicit val creatureFormat = PlayJson.format[Creature]

现在,这两行都有效

val mcJson = PlayJson.toJson(Creature("John Doe", false, 100, new SqlDate(1368430000000L)))
val mcObj = PlayJson.fromJson[Creature](PlayJson.obj("name"-> "Abul Khan", "isDead"-> true, "weight"-> 115, "dob"-> "17-05-2011")).getOrElse(null)

答案 1 :(得分:1)

默认情况下,java.util.Date Json serializer会生成一个包含日期时间戳的数字。

或者,您可以使用日期序列化程序生成包含日期表示的String。但是,由于JSON中没有日期的标准表示,因此您必须明确提供用于生成文本表示的模式:

implicit val creatureFormat = (
  (__ \ "name").format[String] and
  (__ \ "isDead").format[Boolean] and
  (__ \ "weight").format[Float] and
  (__ \ "dob").format(sqlDateWrites("YYYY-MM-DD"))(sqlDateReads("YYYY-MM-DD"))
)(Creature.apply, unlift(Creature.unapply))

答案 2 :(得分:0)

由于您需要字符串,因此必须将所有字符串转换为字符串并丢失输入内容。

Json.toJson(
  Creature(
    "John Doe", "false", "100.0",(new java.sql.Date(1363456800000)).toString
  )
)