5

I have a Scala case class

case class Example(name: String, number: Int)

and a companion object

object Example {
  implicit object ExampleFormat extends Format[Example] {
    def reads(json: JsValue) = {
      JsSuccess(Example(
       (json \ "name").as[String],
       (json \ "number").as[Int]))
     }

     def writes(...){}
   }
}

which converts JSON to Scala object.

When JSON is valid (i.e. {"name":"name","number": 0} it works fine. However, when number is in quotes {"name":"name","number":"0"} I get an error: validate.error.expected.jsnumber.

Is there a way to implicitly convert String to Int in such a case (assuming that the number is valid) ?

4

1 回答 1

8

You can easily handle this case with the Json combinators, thanks to the orElse helper. I rewrote your json formater with the new syntax introduced by Play2.1

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

object Example {
  // Custom reader to handle the "String number" usecase
  implicit val reader = (
    (__ \ 'name).read[String] and
    ((__ \ 'number).read[Int] orElse (__ \ 'number).read[String].map(_.toInt))
  )(Example.apply _)

  // write has no specificity, so you can use Json Macro
  implicit val writer = Json.writes[Example] 
}

object Test extends Controller {
  def index = Action {
    val json1 = Json.obj("name" -> "Julien", "number" -> 1000).as[Example]
    val json2 = Json.obj("name" -> "Julien", "number" -> "1000").as[Example]
    Ok(json1.number + " = " + json2.number) // 1000 = 1000
  }
}
于 2013-01-27T20:43:47.340 回答