我已经在这个特定问题上停留了大约一个星期,我想在这里将其写成一个问题,以阐明我的想法并获得一些指导。
所以我有一个具有java.sql.Timestamp字段的案例类:
case class Request(id: Option[Int], requestDate: Timestamp)
并且我想将其转换为JsObject
val q = Query(Requests).list // This is Slick, a database access lib for Scala
printList(q)
Ok(Json.toJson(q)) // and this is where I run into trouble
“未找到类型为List [models.Request]的Json解串器。请尝试为此类型实现隐式Writes或Format。”好的,那很有道理。
所以在Play documentation here之后,我尝试编写格式...
implicit val requestFormat = Json.format[Request] // need Timestamp deserializer
implicit val timestampFormat = (
(__ \ "time").format[Long] // error 1
)(Timestamp.apply, unlift(Timestamp.unapply)) // error 2
Description Resource Path Location Type overloaded method value format with alternatives:
(w: play.api.libs.json.Writes[Long])(implicit r: play.api.libs.json.Reads[Long])play.api.libs.json.OFormat[Long]
<and>
(r: play.api.libs.json.Reads[Long])(implicit w: play.api.libs.json.Writes[Long])play.api.libs.json.OFormat[Long]
<and>
(implicit f: play.api.libs.json.Format[Long])play.api.libs.json.OFormat[Long]
cannot be applied to (<error>, <error>)
显然像这样导入(请参阅documentation“ ctrl + F导入”)使我陷入麻烦:
import play.api.libs.json._ // so I change this to import only Format and fine
import play.api.libs.functional.syntax._
import play.api.libs.json.Json
import play.api.libs.json.Json._
现在过载错误消失了,我遇到了更多麻烦:not found: value __
我已经按照文档中的说明输入了.../functional.syntax._
! This guy遇到了同样的问题,但是导入为他解决了!所以为什么?!我认为这可能只是Eclipse的问题,并且无论如何都尝试play run
...没什么改变。精细。编译器总是正确的。
导入的play.api.lib.json.JsPath,将__
更改为JsPath
,并添加了Wallah:
value apply is not a member of object java.sql.Timestamp
value unapply is not a member of object java.sql.Timestamp
[我也尝试通过改变大头钉并为此写一个Write(而不是Format),而没有遵循__
的新功能(original blog post the official docs are based on/copy-pasted from):
// I change the imports above to use Writes instead of Format
implicit val timestampFormat = new Writes[Timestamp]( // ERROR 3
def writes(t: Timestamp): JsValue = { // ERROR 4 def is underlined
Json.obj(
/* Returns the number of milliseconds since
January 1, 1970, 00:00:00 GMT represented by this Timestamp object. */
"time" -> t.getTime()
)
}
)
错误3:trait Writes is abstract, cannot be instantiated
错误4:illegal start of simple expression
至此,我才刚刚起步,所以我将回到我的其余部分,并从第一段代码中进行报告
我对任何可以让我摆脱编码痛苦的人表示感谢
不一定是您需要的apply
或unapply
功能。它是a)构造需要给定一些参数的任何类型的函数的函数,以及b)将该类型的实例转换为值的元组(通常与输入参数匹配的函数)的函数。]
使用Scala case类免费获得的apply
和unapply
函数正是这样做的,因此使用它们很方便。但是您总是可以自己编写。
通常,您可以使用类似这样的匿名功能来做到这一点:
import java.sql.Timestamp
import play.api.libs.functional.syntax._
import play.api.libs.json._
implicit val timestampFormat: Format[Timestamp] = (
(__ \ "time").format[Long]
)((long: Long) => new Timestamp(long), (ts: Timestamp) => (ts.getTime))
但是!在这种情况下,您会受到API的限制,该API会阻止您编写仅具有一个值的格式。根据here解释了此限制this answer。
对您来说,一种可行的方法是使外观看起来更复杂:
import java.sql.Timestamp
import play.api.libs.functional.syntax._
import play.api.libs.json._
implicit val rds: Reads[Timestamp] = (__ \ "time").read[Long].map{ long => new Timestamp(long) }
implicit val wrs: Writes[Timestamp] = (__ \ "time").write[Long].contramap{ (a: Timestamp) => a.getTime }
implicit val fmt: Format[Timestamp] = Format(rds, wrs)
// Test it...
val testTime = Json.obj("time" -> 123456789)
assert(testTime.as[Timestamp] == new Timestamp(123456789))