First, the .as[JsValue]
in your second method isn't really necessary—all it does is look up the Reads
instance for JsValue
, which just passes through its argument and never fails.
If you want to go the route you suggest above (defining the Opt
-less version in terms of the other), Scalaz provides some slightly more concise syntax:
def readString(j: JsValue, key: String): Validation[String, String] =
readStringOpt(j, key).flatMap(_.toSuccess(s"Missing field $key"))
This will give you a deprecation warning in recent versions of Scalaz, however, since Validation
does not have a monad instance and its flatMap
is kind of a lie. This means you have two options (apart from ignoring the deprecation warning): you can switch to \/
, which is monadic, or you can use a fold instead:
def readString(j: JsValue, key: String): Validation[String, String] =
readStringOpt(j, key).fold(_.failure, _.toSuccess(s"Missing field $key"))
Which is a little more verbose, but it puts you on the right side of the validation-is-not-a-monad gods.