我有基于播放框架的 json rest api 应用程序,并且希望在解析传入请求时接收有关验证错误的信息。除了从 json 数组到 json 值的转换之外,一切正常。我要实现的Json结构:
{
"errors": {
"name": ["invalid", "tooshort"],
"email": ["invalid"]
}
}
当我尝试实现一个示例时,它运行良好:
def error = Action {
BadRequest(obj(
"errors" -> obj(
"name" -> arr("invalid", "tooshort"),
"email" -> arr("invalid")
)
))
}
当我试图像这样提取变化的部分时:
def error = Action {
val e = Seq("name" -> arr("invalid", "tooshort"), "email" -> arr("invalid"))
// in real app it will be Seq[(JsPath, Seq[ValidationError])]
BadRequest(obj(
"errors" -> obj(e: _*)
))
}
我得到一个编译器错误:
类型不匹配; 找到:Seq[(String, play.api.libs.json.JsArray)] 需要:Seq[(String, play.api.libs.json.Json.JsValueWrapper)]
也许我缺少从 JsArray 到 JsValueWrapper 的一些隐式转换?但是,为什么示例在具有相同导入的同一文件中工作正常?
玩 2.1.1,斯卡拉 2.10.0
更新:由于 Julien Lafont 最终代码解决了问题:
implicit val errorsWrites = new Writes[Seq[(JsPath, Seq[ValidationError])]] {
/**
* Maps validation result of Ember.js json request to json validation object, which Ember can understand and parse as DS.Model 'errors' field.
*
* @param errors errors collected after json validation
* @return json in following format:
*
* {
* "errors": {
* "error1": ["message1", "message2", ...],
* "error2": ["message3", "message4", ...],
* ...
* }
* }
*/
def writes(errors: Seq[(JsPath, Seq[ValidationError])]) = {
val mappedErrors = errors.map {
e =>
val fieldName = e._1.toString().split("/").last // take only last part of the path, which contains real field name
val messages = e._2.map(_.message)
fieldName -> messages
}
obj("errors" -> toJson(mappedErrors.toMap)) // Ember requires root "errors" object
}
}
用法:
def create = Action(parse.json) { // method in play controller
request =>
fromJson(request.body) match {
case JsSuccess(pet, path) => Ok(obj("pet" -> Pets.create(pet)))
case JsError(errors) => UnprocessableEntity(toJson(errors)) // Ember.js expects 422 error code in case of errors
}
}