2016-02-03 80 views
0

我使用Play!斯卡拉2.4和我有幾個簡單的例子類像這樣的:是否有可能重寫play.api.libs.json寫入選項的方式?

case class A(a: Option[String]) 

我想重寫Json.toJson方式(A)的作品時,該選項爲空。

這裏是我做了什麼:

implicit val aWrites: Writes[A] = Json.writes[A] 

implicit def ow[T](implicit w: Writes[T]): Writes[Option[T]] = Writes { 
    case None => JsString("[]") 
    case Some(t) => Json.toJson(t) 
} 

Json.toJson(A(a = None)) mustBe Json.parse("""{"a":"[]"}""") 

,但它仍然解析類像往常一樣(即{},而不是{"a":"[]"},因爲我想)。
爲了使測試通過,我能做些什麼?

回答

2

這是不可能的使用Json.writes宏,因爲它是書面特別處理Option使用readNullable[B]。這意味着您將需要使用組合器來定義Writes[A]。不幸的是,爲一個只有一個字段的對象定義Writes要比具有更多字段的對象更麻煩一些。

implicit val aWrites: Writes[A] = Writes(a => Json.obj("a" -> a.a)) 

scala> Json.toJson(A(None)) 
res8: play.api.libs.json.JsValue = {"a":"[]"} 

例具有多個字段:

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

case class A(a: Option[String], b: Int) 

implicit val aWrites: Writes[A] = (
    (__ \ "a").write[Option[String]] and 
    (__ \ "b").write[Int] 
)(unlift(A.unapply)) 

scala> Json.toJson(A(None, 10)) 
res0: play.api.libs.json.JsValue = {"a":"[]","b":10} 
+0

感謝您的回覆,我知道這樣做的方式,但在我的應用案例類包含更多的領域,我有很多案例類(對不起,我的問題不清楚)。這就是爲什麼我正在尋找一種通用的方式,以便不重寫每個作家......你能解釋一下爲什麼對於一個有更多字段的對象來說不那麼麻煩嗎? – Simon

+0

@Simon我用一個例子更新了我的答案。如果這些case類的'Writes'正在使用'Json.writes [A]',那麼重寫它們是不可避免的。 –

+1

以下是使用'writeNullable'的宏的相關部分,它將忽略'Writes [Option [A]]'並執行它自己的操作:https://github.com/playframework/playframework/blob/ec9de32196ae967619251cf6d61442fb27c88fe0/framework/ src/play-json/src/main/scala/play/api/libs/json/JsMacroImpl.scala#L176-L179 –

0

你需要改變你的aWrites與下面的一個補充"a":部分:

implicit val aWrites: Writes[A] = new Writes[A] { 
    override def writes(o: A): JsValue = 
    Json.obj("a" -> Json.toJson(o.a)) 
} 

編輯:使用的apply方法Writes物體更清晰,斯卡拉一個更好的做法,所以我建議你使用@ mz的回答。

+0

正如我告訴到m-E,我正在尋找一個通用的解決方案,遺憾的是,我的問題是不明確有關。 – Simon

相關問題