12

Reading through this article, I can't figure out how to convert my Some(JsValue) to a String.

Example:

val maybeString: Option[JsValue] = getSomeJsValue(); // returns Some(JsValue)

val str: String = maybeString match {
  case Some(x) => x.as[String]
  case _       => "0"
}

run-time error:

play.api.Application$$anon$1: Execution exception[[JsResultException: JsResultException(errors:List((,List(ValidationErr
or(validate.error.expected.jsstring,WrappedArray())))))]]
        at play.api.Application$class.handleError(Application.scala:289) ~[play_2.10.jar:2.1.3]
1
  • If you're sure to have a JsString: maybeString.map(_.toString) Commented Aug 29, 2013 at 20:20

2 Answers 2

7

You want to compose multiple Options, that's what flatMap is for:

maybeString flatMap { json =>
  json.asOpt[String] map { str =>
    // do something with it
    str
  }
} getOrElse "0"

Or as a for comprehension:

(for {
  json <- maybeString
  str <- json.asOpt[String]
} yield str).getOrElse("0")

I'd also advise to work with the value inside the map and pass the Option around, so a None will be handled by your controller and mapped to a BadRequest for example.

Sign up to request clarification or add additional context in comments.

2 Comments

OK - your first implementation was successful for me. I used asOpt[Long] instead since asOpt[String] didn't match, i.e. returned "0"
try to avoid using 'get' or 'getOrElse'
3

Your error comes from the fact that you don't impose enough condition on x's type : maybeString is an Option[JsValue], not Option[JsString]. In the case maybeString is not an Option[JsString], the conversion fails and raises and exception.

You could do this :

val str: String = maybeString match {
  case Some(x:JsString) => x.as[String]
  case _       => "0"
}

Or you could use asOpt[T] instead of as[T], which returns Some(_.as[String]) if the conversion was successful, None otherwise.

5 Comments

Well, if I have Option[JsValue], how can I convert that to a String?
@Kevin maybeString.map(_.toString).getOrElse("defaultString"), but that will transform all Some[JsValue] (ie give you "defaultString" only when maybeString is empty). I thought from your question you wanted to get the string representation if your Option[JsValue] happened to be a Some[JsString] and get a default value otherwise.
(too slow to edit previous comment) It will give you "defaultString" only when maybeString is None *
I believe that I understand you're helping me on how to convert a Some(JsString) to a String, but what if I have a Some(JsValue)? (Sorry if I'm repeating myself. I'm just not seeing how to go from Some(JsValue) to String...)
Doesn't maybeString.map(_.toString).getOrElse("default") work ? This should take any Option[JsValue] and return its string representation, or "default" if the option is empty. What's the error message ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.