Reputation: 2204
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) ?
Upvotes: 5
Views: 2747
Reputation: 7877
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
}
}
Upvotes: 8