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) ?
Argonaut is a great library. It's by far the best JSON library for Scala, and the best JSON library on the JVM. If you're doing anything with JSON in Scala, you should be using Argonaut. circe is a fork of Argonaut with a few important differences.
JSONPath is an expression language to parse JSON data. It's very similar to the XPath expression language to parse XML data. The idea is to parse the JSON data and get the value you want.
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With