2014-09-06 59 views
1

這是一個人爲的例子來說明這一點。我知道我可以使用LocalDate和LocalTime來代替DateTime,但是這會錯過問題的關鍵點,即在寫出它們之前以某種方式處理字段值。如何使用組合器在寫入JSON之前處理對象字段值

case class Test(
    id: Long, dateOnly: DateTime, timeOnly: DateTime, comments: Option[String]) 

爲了寫爲JSON我開始與此:

implicit val testWrites: Writes[Test] = (
    (__ \ "id"  ).write[Long]   and 
    (__ \ "dateOnly").write[DateTime]  and 
    (__ \ "timeOnly").write[DateTime]  and 
    (__ \ "comments").write[Option[String]] 
)(unlift(Test.unapply)) 

另外,假設在沒有註釋的對象實例。

這將輸出類似:

{"id": 123, 
"dateOnly": "1409952730536", 
"timeOnly": "1409953948034", 
"comments": null} 

有一個默認的寫入實施日期時間輸出值作爲毫秒。

我想輸出是這樣的:

{"id": 123, 
"dateOnly": "2014-03-08", 
"timeOnly": "15:24", 
"comments": ""} 

所以我想我需要通過一個函數調用來處理dateOnly,timeOnly和註釋字段的值來獲得我想要的東西最終JSON前值被寫出。

我至少需要自定義與日期時間的模式,像這樣寫:

def dateTimeWrites(pattern: String): Writes[DateTime] = new Writes[DateTime] { 
    def writes(d: DateTime): JsValue = JsString(d.toString(pattern)) 
} 

我看不到我應該如何將這一習俗寫入實現到測試將實施,也不能我看到我將如何爲兩個不同的日期/時間字段指定兩種不同的模式。

我也不能看到如何發出一個空字符串而不是空的評論 - writeNullable會完全忽略評論字段,我不希望這樣。

鑑於經過多次搜索,我似乎無法找到任何我想要做的事情的可理解的例子,我懷疑我的做法是錯誤的。

回答

2

沒有必要爲您的自定義Writes[DateTime],圖書館提供一個。

val myDateWrites = Writes.jodaDateWrites("x-MM-dd") 

val myTimeWrites = Writes.jodaDateWrites("HH:mm") 

val emptyStringWrites = Writes[Option[String]](_.map(JsString).getOrElse(JsString(""))) 

implicit val testWrites: Writes[Test] = (
    (__ \ "id"  ).write[Long]    and 
    (__ \ "dateOnly").write(myDateWrites)  and 
    (__ \ "timeOnly").write(myTimeWrites)  and 
    (__ \ "comments").write(emptyStringWrites) 
)(unlift(Test.unapply)) 

然後你會得到:

scala> val test = Test(123, DateTime.now(), DateTime.now(), None) 
test: Test = Test(123,2014-09-06T00:27:32.903-06:00,2014-09-06T00:27:32.903-06:00,None) 

scala> Json.toJson(test) 
res6: play.api.libs.json.JsValue = {"id":123,"dateOnly":"2014-09-06","timeOnly":"00:27","comments":""} 

所有這一切都在Scaladoc解釋爲JsPathhttps://www.playframework.com/documentation/2.2.x/api/scala/index.html#play.api.libs.json.JsPath

如果你看一下函數的定義,你會看到def write[T](implicit w: Writes[T])。當你指定.write[String]時,編譯器在某處找到Writes[String]play.api.libs.json.Writes._),並將它傳遞給你的那個函數。如果你想提供你自己的,只需要明確地傳遞它,就像我上面所做的那樣。

相關問題