Play Framework:如何在验证时将字符串转换为数字 JSON
Play Framework: How to convert strings to numbers while validating JSON
给出以下 JSON..
{
"ask":"428.00",
"bid":"424.20"
}
...我需要将 ask
和 bid
的值转换为数字:
{
"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))
}
}
)
}
上面的代码只验证了值,当然没有用转换后的数字替换原始字符串。如何在验证时将字符串值转换为数字?
编辑
只想分享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))
}
}
)
}
如果您将 toNumber
设为 Reads[JsNumber]
而不是 Reads[Double]
(只需将 number
包裹在 JsNumber
中),那么您可以使用 transform
连同 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))))))
从某种意义上说,变形金刚 是 验证器。您可以使用 transform
简单地转换值,如果转换无效则得到 JsError
,而不是检查某物是否有效,然后转换它。阅读更多关于 transform
here.
给出以下 JSON..
{
"ask":"428.00",
"bid":"424.20"
}
...我需要将 ask
和 bid
的值转换为数字:
{
"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))
}
}
)
}
上面的代码只验证了值,当然没有用转换后的数字替换原始字符串。如何在验证时将字符串值转换为数字?
编辑
只想分享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))
}
}
)
}
如果您将 toNumber
设为 Reads[JsNumber]
而不是 Reads[Double]
(只需将 number
包裹在 JsNumber
中),那么您可以使用 transform
连同 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))))))
从某种意义上说,变形金刚 是 验证器。您可以使用 transform
简单地转换值,如果转换无效则得到 JsError
,而不是检查某物是否有效,然后转换它。阅读更多关于 transform
here.