定义读取[X],其中X具有私有构造函数

时间:2016-07-01 12:41:31

标签: scala playframework-2.0

给定select f1,f2,sum(f2) over(order by f1) running_total, Floor(sum(f2) over(order by f1) / 40) [rank] from [dbo].[Sheet1$] 类带有'智能构造函数',即Person中只有“有效”值会构造Person#build

Person

我将case class Person private(age: Int) object Person { def build(age: Int): Option[Person] = if (age >= 0 && age <= 125) Some(Person(age)) else None } 放入Reads[Person]的伴侣对象中创建了Person

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

  implicit val reads: Reads[Person] = 
   (__ \ 'age).read[Int].map(a => 
    Person.build(a).getOrElse(throw new RuntimeException("invalid age")            
   ) 

有更好的方法吗?如果可能的话,我宁愿避免这种例外。

1 个答案:

答案 0 :(得分:2)

如果您愿意放弃播放功能样式,可以使用JsResult monad:

new Format[Person] {
  override def writes(o: Person): JsValue = ???

  override def reads(json: JsValue): JsResult[Person] = {
    try{
      json.as[JsObject].value.get("age")
        .flatMap(age => Person.build(age.as[Int])).map(JsSuccess(_))
        .getOrElse(JsError("wrong age"))
    } catch {
      case e: Exception =>
        JsError("wrong age")
    }
  }
}

val person = Json.toJson(Person.build(30))

val parsed: \/[String, Person] =  person.validate[Person].map(\/-(_)).getOrElse(-\/("some bad request"))

所以它比我在评论中建议的要复杂一点,但基本上你可以将解析包装成一个方法,将JsSuccess转换为右边,将JsError转换为左边, try/catch我用来捕捉发送的json不是一个对象而只是一个值或者如果age字段不是整数的情况。