2015-08-19 33 views
0

我有一個場景,解析JSON時的情形類這樣播放JSON組合子驗證至少一個字段中指定

implicit val userRead: Reads[User] = (
    (__ \ "name").read[String] ~ 
     (__ \ "email").readNullable[String] ~ 
     (__ \ "phone").readNullable[String] ~ 
     Reads.pure(None) 
    )(User.apply _) 

我不要求兩個emailphone可用,但在其中至少有一個必須可用。

在我的例子類的定義,我可以阻止他們兩人都是空的,

case class User(name: String, email: Option[String], phone: Option[String], id: Option[Long] = None) { 
    require(email.nonEmpty || phone.nonEmpty, "must have at least an email or phone number") 
} 

的情況。但是,這樣做會產生異常,和一個500個狀態響應,當這應該是一個由於用戶輸入而導致的400錯誤。

我當然可以在我的控制器中手動執行驗證,但我想知道是否有更乾淨的方法來執行此操作。

回答

1

我只能建議你寫自己的「讀取」手動

case class A(i: Option[Int], j: Option[Int]) 

implicit val reads: Reads[A] = new Reads[A] { 
    override def reads(json: JsValue): JsResult[A] = { 
    (for { 
     i <- (json \ "i").validateOpt[Int] 
     j <- (json \ "j").validateOpt[Int] 
    } yield A(i, j)) 
     .filter(JsError("both values can't be empty"))(a ⇒ a.j.nonEmpty || a.i.nonEmpty) 
    } 
    } 

,並測試:

scala> Json.parse("""{ "i" : 1} """).validate[A] 
res4: play.api.libs.json.JsResult[A] = JsSuccess(A(Some(1),None),) 


scala> Json.parse("""{} """).validate[A] 
res5: play.api.libs.json.JsResult[A] = JsError(List((,List(ValidationError(List(from and to in range can't be both empty),WrappedArray()))))) 
+0

感謝Tyth,至少這樣我就不必在我的所有代碼驗證。 – Khanetor

相關問題