Play Framework:如何在验证JSON时将字符串转换为数字

时间:2015-04-17 09:34:56

标签: json scala playframework

给出以下JSON ..

{
    "ask":"428.00",
    "bid":"424.20"
}

...我需要将askbid的值转换为数字:

{
    "ask": 428.00,
    "bid": 424.20
}

为此,我创建了一个验证器,它读取字符串值并将其传递给方法toNumber,方法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)) } } ) } 验证并转换给定的字符串:

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))
      }
    }
  )
}

上面的代码只验证值,但当然不会用转换后的数字替换原始字符串。在验证时如何将字符串值转换为数字?

修改

只是想分享Ben提供的解决方案:

{{1}}

1 个答案:

答案 0 :(得分:1)

如果您使toNumber成为Reads[JsNumber]而不是Reads[Double](只需将number包裹在JsNumber中),那么您可以使用transformupdate一起使用:

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))))))

从某种意义上说,变形金刚验证者。您可以使用transform简单地转换值,而不是检查某些内容是否有效,然后对其进行转换,如果转换无效,则可以使用JsError。详细了解transform here