Given the following JSON..
{
"ask":"428.00",
"bid":"424.20"
}
... I need to convert the values of ask and bid to numbers:
{
"ask": 428.00,
"bid": 424.20
}
To do that, I've created a validator that reads the string value and passes it to method toNumber, which validates and converts the given string:
def validate = (
((__ \ 'ask).json.pickBranch(Reads.of[JsString] <~ toNumber)) ~
((__ \ 'bid).json.pickBranch(Reads.of[JsString] <~ toNumber))
).reduce
private def toNumber(implicit reads: Reads[String]) = {
Reads[Double](js =>
reads.reads(js).flatMap { value =>
parse[Double](value) match {
case Some(number) => JsSuccess(number)
case _ => JsError(ValidationError("error.number", value))
}
}
)
}
The code above only validates the value but of course does not replace the original string with the converted number. How do I convert string values to numbers while validating?
EDIT
Just wanted to share the solution provided by Ben:
def validate = (
((__ \ 'ask).json.update(toNumber)) ~
((__ \ 'bid).json.update(toNumber))
).reduce
private def toNumber(implicit reads: Reads[String]) = {
Reads[JsNumber](js =>
reads.reads(js).flatMap { value =>
parse[Double](value) match {
case Some(number) => JsSuccess(JsNumber(number))
case _ => JsError(ValidationError("error.number", value))
}
}
)
}
If you make toNumber a Reads[JsNumber] instead of a Reads[Double] (simply by wrapping number in JsNumber), then you can use transform together with update:
val transformer = (__ \ "ask").json.update(toNumber)
val json = Json.parse(""" { "ask" : "44" } """)
json.transorm(transformer) //JsSuccess({"ask":44.0},/ask)
val json = Json.parse(""" { "ask" : "foo" } """)
json.transorm(transformer) //JsError(List((/ask,List(ValidationError(error.number,WrappedArray(foo))))))
In a sense, transformers are validators. Instead of checking if something is valid, and then transforming it, you can use transform to simply transform the value, and get a JsError if the transformation is invalid. Read more about transform here.
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