简化2个类似的json辅助函数

时间:2013-11-19 02:08:50

标签: json scala playframework-2.0 scalaz

我有两个相似的功能。一个成功后返回一个String,第二个成功时返回一个Option [String]。如何以更优雅的方式编写它,也许在第二个函数中调用第一个函数?谢谢!

  private def readString(j: JsValue, key: String): Validation[String, String] = {
    j \ key match {
      case j: JsString =>
        Success(j.value)
      case j: JsUndefined =>
        Failure(s"Missing field $key")
      case j: JsValue =>
        Failure(s"Field $key value is not a string")
    }
  }

  private def readStringOpt(j: JsValue, key: String): Validation[String, Option[String]] = {
    (j \ key).as[JsValue] match {
      case j: JsString =>
        j.value.some.success
      case j: JsUndefined =>
        None.success
      case x =>
        Failure(s"Field $key value is not a string")
    }
  }

1 个答案:

答案 0 :(得分:2)

首先,你的第二个方法中的.as[JsValue]并不是必需的 - 它所做的只是查找Reads的{​​{1}}实例,它只是通过它的参数而永远不会失败

如果你想走上面你建议的路线(根据另一个定义JsValue - 更少的版本),Scalaz提供了一些稍微简洁的语法:

Opt

但是,这会在最新版本的Scalaz中提供弃用警告,因为def readString(j: JsValue, key: String): Validation[String, String] = readStringOpt(j, key).flatMap(_.toSuccess(s"Missing field $key")) 没有monad实例且其Validation有点谎言。这意味着您有两个选项(除了忽略弃用警告):您可以切换到flatMap,这是monadic,或者您可以使用折叠代替:

\/

哪个更冗长,但它会让你站在验证的右侧 - 不是一个单身的神。