Converting JsValue to String

15,787

Solution 1

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.

Solution 2

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.

Share:
15,787

Related videos on Youtube

Kevin Meredith
Author by

Kevin Meredith

Scala developer Haskell student https://www.linkedin.com/pub/kevin-meredith/11/22a/334

Updated on July 08, 2022

Comments

  • Kevin Meredith
    Kevin Meredith almost 2 years

    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]
    
  • Kevin Meredith
    Kevin Meredith over 10 years
    Well, if I have Option[JsValue], how can I convert that to a String?
  • Marth
    Marth over 10 years
    @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.
  • Marth
    Marth over 10 years
    (too slow to edit previous comment) It will give you "defaultString" only when maybeString is None *
  • Kevin Meredith
    Kevin Meredith over 10 years
    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...)
  • Kevin Meredith
    Kevin Meredith over 10 years
    OK - your first implementation was successful for me. I used asOpt[Long] instead since asOpt[String] didn't match, i.e. returned "0"
  • Marth
    Marth over 10 years
    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 ?
  • Niels
    Niels over 8 years
    try to avoid using 'get' or 'getOrElse'