在没有 JSPath 的 Play 框架中验证 JSON
Validate JSON in Play framework without JSPath
我已经预先定义了 class MyClass
以下 JSON 结构:
{
"key1": [
// Objects of MyClass
],
"key2": [
// Objects of MyClass
],
"key3": [
// Objects of MyClass
]
}
key1, key2, key3
是可选的(至少有一个必须存在,但我不需要验证它)
根据 Play 框架文档,我需要执行以下操作:
implicit val myClassReads: Reads[] = (
(JsPath \ "key1").read[List[MyClass]] and
(JsPath \ "key2").read[List[MyClass]] and
(JsPath \ "key3").read[List[MyClass]]
)
但是这种方法有一些缺点:
key1, key2, key3
的数据类型总是MyClass
)。重复 read[MyClass]
似乎多余。
如果 JSON 架构发生变化而有 key1, key2, ... key100
怎么办?代码变得很乱
如何编写将 read[MyClass]
应用于所有字段的自定义验证器?
是这样的吗?
def convertJsonToListModel[T](json: JsValue)(implicit reads: Reads[T]): List[T] = {
val conversionResult: JsResult[List[T]] = json.validate[List[T]]
conversionResult match {
case s: JsSuccess[List[T]] => s.get
case e: JsError => e.get
}
}
Play JSON 具有针对产品类型(例如案例 类)的自动格式推导。
您可以在文档中找到更多详细信息:https://www.playframework.com/documentation/latest/ScalaJsonAutomated
我想在你的情况下,这会像下一个:
import play.api.libs.json._
case class MyClass(value: String)
object MyClass {
implicit format = Json.format[Resident]
}
case class MyClassContainer(key1: List[MyClass], key2: List[MyClass], key3: List[MyClass])
object MyClassContainer {
implicit format = Json.format[MyClassContainer]
}
希望这会有所帮助。
如果您正在使用 Play Json 2.8.x,您可以这样做:
val result = json.validate[Map[String, List[MyClass]]]
Is it possible to validate whether the JSON keys are in ALLOWED_KEYS: List[String] with your approach?
您也可以使用另一种类型作为 Map
的键,只要您为该类型定义一个 KeyReads
实例即可。所以你可以使用一个枚举,只有有限数量的可能值。或者您可以使用优化类型(例如使用 "refined" 库)等等。
限制键的可能值的最简单方法是检查转换后的结果映射:
val ALLOWED_KEYS = Set("key1", "key2", ...)
val result = json.validate(
Reads.verifying[Map[String, List[MyClass]]](_.keySet.subsetOf(ALLOWED_KEYS))
)
或者您也可以根据需要预先检查密钥:
val result = json.validate(
Reads.verifying[JsObject](_.keys.subsetOf(ALLOWED_KEYS))
.andThen(Reads.of[Map[String, List[MyClass]]])
)
我已经预先定义了 class MyClass
以下 JSON 结构:
{
"key1": [
// Objects of MyClass
],
"key2": [
// Objects of MyClass
],
"key3": [
// Objects of MyClass
]
}
key1, key2, key3
是可选的(至少有一个必须存在,但我不需要验证它)
根据 Play 框架文档,我需要执行以下操作:
implicit val myClassReads: Reads[] = (
(JsPath \ "key1").read[List[MyClass]] and
(JsPath \ "key2").read[List[MyClass]] and
(JsPath \ "key3").read[List[MyClass]]
)
但是这种方法有一些缺点:
key1, key2, key3
的数据类型总是MyClass
)。重复read[MyClass]
似乎多余。如果 JSON 架构发生变化而有
key1, key2, ... key100
怎么办?代码变得很乱
如何编写将 read[MyClass]
应用于所有字段的自定义验证器?
是这样的吗?
def convertJsonToListModel[T](json: JsValue)(implicit reads: Reads[T]): List[T] = {
val conversionResult: JsResult[List[T]] = json.validate[List[T]]
conversionResult match {
case s: JsSuccess[List[T]] => s.get
case e: JsError => e.get
}
}
Play JSON 具有针对产品类型(例如案例 类)的自动格式推导。 您可以在文档中找到更多详细信息:https://www.playframework.com/documentation/latest/ScalaJsonAutomated 我想在你的情况下,这会像下一个:
import play.api.libs.json._
case class MyClass(value: String)
object MyClass {
implicit format = Json.format[Resident]
}
case class MyClassContainer(key1: List[MyClass], key2: List[MyClass], key3: List[MyClass])
object MyClassContainer {
implicit format = Json.format[MyClassContainer]
}
希望这会有所帮助。
如果您正在使用 Play Json 2.8.x,您可以这样做:
val result = json.validate[Map[String, List[MyClass]]]
Is it possible to validate whether the JSON keys are in ALLOWED_KEYS: List[String] with your approach?
您也可以使用另一种类型作为 Map
的键,只要您为该类型定义一个 KeyReads
实例即可。所以你可以使用一个枚举,只有有限数量的可能值。或者您可以使用优化类型(例如使用 "refined" 库)等等。
限制键的可能值的最简单方法是检查转换后的结果映射:
val ALLOWED_KEYS = Set("key1", "key2", ...)
val result = json.validate(
Reads.verifying[Map[String, List[MyClass]]](_.keySet.subsetOf(ALLOWED_KEYS))
)
或者您也可以根据需要预先检查密钥:
val result = json.validate(
Reads.verifying[JsObject](_.keys.subsetOf(ALLOWED_KEYS))
.andThen(Reads.of[Map[String, List[MyClass]]])
)