我有一个相当复杂的表单,允许用户选择一些下拉值并在输入框中输入文本等。
该表单本质上是"高级搜索"类型的表单。
def search = Action(parse.json) { request =>
val sR = request.body.validate[SearchRequest]
sR.fold(
errors => {
BadRequest(Json.obj("status" -> "KO", "message" -> JsError.toJson(errors)))
},
searchRequest => {
Logger.debug(s"searchRequest is $searchRequest")
val sr = SearchResults(10)
Ok(Json.toJson(sr))
}
)
}
假设我有一个下拉列表,其中包含以下值:
IsGreaThan
IsLessThan
EqualTo
我的搜索请求如下所示:
case class SearchRequest(operator: String)
但我不希望用户可能发送错误数据,即"IsGreaterThan"、"IsLessThan"等以外的字符串。
当 JSON 绑定到搜索请求对象时,如何使其为强类型?
我认为您正在寻找的是枚举类型的Reads
实例; 即:
声明一个特定的SearchOperator
枚举:
object SearchOperator extends Enumeration {
type SearchOperator = Value
val IsGreaThan = Value("IsGreaThan")
val IsLessThan = Value("IsLessThan")
val EqualTo = Value("EqualTo")
}
在SearchRequest
案例类中使用它:
case class SearchRequest(lhs: Int, operator: SearchOperator, rhs:Int)
定义如何阅读它:
object SearchRequestJson {
implicit val soReads = Reads.enumNameReads(SearchOperator)
implicit val srReads = Json.reads[SearchRequest]
}
关键是 2.4 版添加到 Play 中的Reads.enumNameReads
函数,并为您的情况保存了一堆样板。
现在,如果我提交非法值作为搜索请求的一部分:
{ "lhs": 42, "operator": "NotEqualTo", "rhs": 44 }
我得到一个:
JsError(
List(
(/operator, List(
ValidationError(
List(error.expected.enumstring),
WrappedArray()
)
))
)
)