Scala Play 2.6:解析JSON时实现字段间约束校验
解决Play JSON解析时的字段依赖验证问题
没问题,我来帮你实现这个需求——在解析JSON到Range类时,确保min小于max。下面是两种可行的实现方式,都能满足你的测试要求:
方法一:基于自动生成Reads + 过滤验证
这种方式利用Play JSON自动生成的Reads,再附加自定义的验证逻辑,代码更简洁:
import org.scalatest.{FlatSpec, Matchers} import play.api.libs.json.{JsError, Json, Reads} class JsonReadsTest extends FlatSpec with Matchers { "Json" should "validate min < max during reads" in { val reads: Reads[Range] = Json.reads[Range] .filter(JsError("max should be superior to min"))(range => range.min < range.max) val invalidJson = Json.obj("min" -> 3, "max" -> 2) reads.reads(invalidJson) shouldBe JsError("max should be superior to min") // 可选:验证合法的JSON能正确解析 val validJson = Json.obj("min" -> 2, "max" -> 3) reads.reads(validJson).get shouldBe Range(2, 3) } } case class Range(min: Int, max: Int)
方法二:手动构建Reads(更灵活的控制)
如果你需要更细粒度地控制解析流程,可以用for推导式手动构建Reads:
import org.scalatest.{FlatSpec, Matchers} import play.api.libs.json.{JsError, Json, Reads, JsPath} class JsonReadsTest extends FlatSpec with Matchers { "Json" should "validate min < max during reads" in { val reads: Reads[Range] = for { min <- (JsPath \ "min").read[Int] max <- (JsPath \ "max").read[Int] // 验证min < max,不满足则返回错误 _ <- Reads.cond( min < max, (), JsError("max should be superior to min") ) } yield Range(min, max) val invalidJson = Json.obj("min" -> 3, "max" -> 2) reads.reads(invalidJson) shouldBe JsError("max should be superior to min") val validJson = Json.obj("min" -> 1, "max" -> 5) reads.reads(validJson).get shouldBe Range(1, 5) } } case class Range(min: Int, max: Int)
代码说明
- 方法一:
Json.reads[Range]会自动根据case class的字段生成基础的Reads,然后调用filter方法添加验证规则——当range.min < range.max不成立时,返回指定的JsError。 - 方法二:通过for推导式依次读取
min和max字段,然后用Reads.cond检查条件。这种方式适合需要在解析过程中做更多自定义逻辑的场景(比如多个字段的复杂依赖验证)。
两种方法都能通过你给出的测试用例,当传入min=3、max=2的JSON时,会返回预期的错误信息。
内容的提问来源于stack exchange,提问作者Maxence Cramet
相关产品推荐
相关产品推荐

