Play JSON 中有没有办法为不是对象(/数组)的东西定义 reader?
Is there a way in Play JSON to define a reader for something that is not an object (/array)?
基本上,我有一个JSON这个形状:
{
"color": "#abcdef"
}
所以我写了一个Reads
:
import java.awt.Color
case class Options(color: Color)
((__ \ "color").read[Color])(Options _)
除了 Color
没有 reader。我的第二次尝试是:
(
Color.decode((__ \ "color").read[String])
)(Options _)
但这显然也不正确。该文档显示了为 { }
(和 [ ]
)创建 reader 的方法,但不是为数字或字符串等“基元”创建的方法。我可以这样做吗?
你可以这样做:
case class Options(color: Color)
object Options {
implicit val colorReads: Reads[Color] = __.read[String].map(Color.decode)
implicit val optionsReads: Reads[Options] = Json.reads[Options]
}
那么用法是:
val b = Json.parse("{ \"color\": \"#abcdef\"}").as[Options]
println(b) // prints: Options(java.awt.Color[r=171,g=205,b=239])
您需要为 Color
定义 Reads
以与 Play Json 基础架构的其余部分保持一致,例如:
import scala.util._
import play.api.libs.json._
import java.awt.Color
case class Options(color: Color)
object Options {
implicit val colorReads: Reads[Color] = {
implicitly[Reads[String]].flatMapResult { value =>
def invalidColor(cause: Throwable) = {
JsError(JsonValidationError(s"Invalid color value: `$value`. Error: ${cause.getMessage}"))
}
def validColor(color: Color) = {
JsSuccess(color)
}
Try(Color.decode(value)).fold(invalidColor, validColor)
}
}
implicit val reads: Reads[Options] = Json.reads
}
val jsonString = """ { "color": "#abcdef" }""".stripMargin
/*
* Prints out: Options(java.awt.Color[r=171,g=205,b=239])
*/
println(Json.parse(jsonString).as[Options])
val invalidColorJsonString = """ { "color": "invalid_color" }""".stripMargin
/*
* Prints out: JsError(List((/color,List(JsonValidationError(List(Invalid color value: `invalid_color`. Error: For input string: "invalid_color"),WrappedArray())))))
*/
println(Json.parse(invalidColorJsonString).validate[Options])
使用的 scala:2.12,sbt:1.4.7,Play Json:2.9.2
基本上,我有一个JSON这个形状:
{
"color": "#abcdef"
}
所以我写了一个Reads
:
import java.awt.Color
case class Options(color: Color)
((__ \ "color").read[Color])(Options _)
除了 Color
没有 reader。我的第二次尝试是:
(
Color.decode((__ \ "color").read[String])
)(Options _)
但这显然也不正确。该文档显示了为 { }
(和 [ ]
)创建 reader 的方法,但不是为数字或字符串等“基元”创建的方法。我可以这样做吗?
你可以这样做:
case class Options(color: Color)
object Options {
implicit val colorReads: Reads[Color] = __.read[String].map(Color.decode)
implicit val optionsReads: Reads[Options] = Json.reads[Options]
}
那么用法是:
val b = Json.parse("{ \"color\": \"#abcdef\"}").as[Options]
println(b) // prints: Options(java.awt.Color[r=171,g=205,b=239])
您需要为 Color
定义 Reads
以与 Play Json 基础架构的其余部分保持一致,例如:
import scala.util._
import play.api.libs.json._
import java.awt.Color
case class Options(color: Color)
object Options {
implicit val colorReads: Reads[Color] = {
implicitly[Reads[String]].flatMapResult { value =>
def invalidColor(cause: Throwable) = {
JsError(JsonValidationError(s"Invalid color value: `$value`. Error: ${cause.getMessage}"))
}
def validColor(color: Color) = {
JsSuccess(color)
}
Try(Color.decode(value)).fold(invalidColor, validColor)
}
}
implicit val reads: Reads[Options] = Json.reads
}
val jsonString = """ { "color": "#abcdef" }""".stripMargin
/*
* Prints out: Options(java.awt.Color[r=171,g=205,b=239])
*/
println(Json.parse(jsonString).as[Options])
val invalidColorJsonString = """ { "color": "invalid_color" }""".stripMargin
/*
* Prints out: JsError(List((/color,List(JsonValidationError(List(Invalid color value: `invalid_color`. Error: For input string: "invalid_color"),WrappedArray())))))
*/
println(Json.parse(invalidColorJsonString).validate[Options])
使用的 scala:2.12,sbt:1.4.7,Play Json:2.9.2