您可以预处理您的JSON以使其与生成的Reads
宏的期望匹配:
我试图以字符串形式读取字段vpid
,而不必编写整个读取函数。
有效的旧代码,除非vpid
是整数。
case class SectionProduct(vpid: Option[String], name: Option[String], quantity: Option[Int]) {}
object SectionProduct {
implicit val config: Aux[WithDefaultValues] = JsonConfiguration[Json.WithDefaultValues](SnakeCase)
implicit val format: OFormat[SectionProduct] = Json.format[SectionProduct]
implicit val writes: OWrites[SectionProduct] = Json.writes[SectionProduct]
// implicit val reads: Reads[SectionProduct] = Json.reads[SectionProduct]
}
新代码,如果可能的话,我试图避免写出整个reads2
块。
val intToString: Reads[String] = implicitly[Reads[Int]].map(x => x.toString)
implicit val reads2: Reads[SectionProduct] = (
((JsPath \ "vpid").readNullable[String] or (JsPath \ "vpid").readNullable[String](intToString)) and
(JsPath \ "name").readNullable[String] and
(JsPath \ "quantity").readNullable[Int]
) (SectionProduct.apply _)
[Play-JSON不为基于宏的编解码器提供每个字段的配置,并且vpid
未使用特定类型定义(同一String
中还有其他可选的SectionProduct
)。] >
使用特定类型,它很容易(并且通过改进键入功能,除了这种特定用法之外,还可以享受其他好处)。>>
import play.api.libs.json._ final class Vpid(val value: String) extends AnyVal object Vpid { import scala.language.implicitConversions @deprecated("Use .value explicitly", "") /* * {{{ * val compatStr: String = new Vpid("foo") * // => compatStr: String = foo * }}} */ implicit def toString(id: Vpid): String = id.value implicit def reads: Reads[Vpid] = Json.valueReads[Vpid].orElse( implicitly[Reads[Int]].map { i => new Vpid(i.toString) }) } case class SectionProduct( vpid: Option[Vpid], name: Option[String], quantity: Option[Int]) implicit val reads: Reads[SectionProduct] = Json.reads
在这种情况下:
val input1 = Json.parse("""{ "vpid": "foo", "name": "bar" }""") input1.validate[SectionProduct] // => JsSuccess(SectionProduct(Some(Vpid@18cc6),Some(bar),None),) val input2 = Json.parse("""{ "vpid": 1, "name": "bar" }""") input2.validate[SectionProduct] // => JsSuccess(SectionProduct(Some(Vpid@31),Some(bar),None),)
您可以预处理您的JSON以使其与生成的Reads
宏的期望匹配:
implicit val reads: Reads[SectionProduct] = Json.reads[SectionProduct].preprocess {
case obj: JsObject =>
obj.as(
Reads
.at[Int](__ \ "vpid")
.map { vpid => obj + ("vpid" -> JsString(vpid.toString)) }
.orElse(Reads.pure(obj))
)
}
您可以预处理您的JSON以使其与生成的Reads
宏的期望匹配: