当JSON值不符合要求时,如何返回友好的API错误信息?
如何在API参数校验不通过时返回友好错误信息
问题背景
我的API在正常请求(JSON与case class匹配)时能正常工作,但当JSON不符合业务校验规则时,不知道怎么返回友好的错误提示。
定义的请求Case Class
case class UpdateUserRequest ( registrationStatus: String, level: Int )
业务校验规则
level值必须在10到20之间registrationStatus的取值只能是"a"、"b"或"c"
当前API路由代码
case updateUser @ PUT -> Root / "users" as user => { for { updateReq <- updateUser.req.as[UpdateUserRequest] // 后续业务逻辑 apiResponse <- Ok(200, true, "") } yield apiResponse }
自定义响应对象
case class ApiResponse( statusCode: Int, success: Boolean, errorMessage: String )
解决方案
1. 给请求类添加校验逻辑
直接在UpdateUserRequest中嵌入校验方法,返回具体的错误信息列表:
case class UpdateUserRequest(registrationStatus: String, level: Int) { // 执行所有规则校验,返回错误信息集合 def validate: List[String] = { val errors = scala.collection.mutable.ListBuffer[String]() // 校验registrationStatus的合法取值 if (!List("a", "b", "c").contains(registrationStatus)) { errors += s"registrationStatus只能是'a'、'b'或'c',当前值为$registrationStatus" } // 校验level的范围 if (level < 10 || level > 20) { errors += s"level必须在10到20之间,当前值为$level" } errors.toList } }
2. 在路由中处理校验结果
修改路由逻辑,先解析请求,再执行校验,根据校验结果返回对应响应:
case updateUser @ PUT -> Root / "users" as user => { updateUser.req.as[UpdateUserRequest].flatMap { updateReq => updateReq.validate match { // 校验通过,执行业务逻辑 case Nil => // 这里写你的业务处理代码 Ok(ApiResponse(200, true, "")) // 校验失败,返回错误提示 case errors => BadRequest(ApiResponse(400, false, errors.mkString("; "))) } }.recover { // 捕获JSON解析错误(比如level传了字符串、字段缺失等) case e: Exception => BadRequest(ApiResponse(400, false, s"请求格式错误:${e.getMessage}")) } }
3. 可选:用自定义错误类型优化结构化校验
如果需要更清晰的错误分类,可以定义专门的错误类型,方便后续扩展:
// 定义错误类型 sealed trait ValidationError case class InvalidRegistrationStatus(value: String) extends ValidationError case class LevelOutOfRange(value: Int) extends ValidationError // 扩展请求类的校验方法 case class UpdateUserRequest(registrationStatus: String, level: Int) { def validate: List[ValidationError] = { val errors = scala.collection.mutable.ListBuffer[ValidationError]() if (!List("a", "b", "c").contains(registrationStatus)) { errors += InvalidRegistrationStatus(registrationStatus) } if (level < 10 || level > 20) { errors += LevelOutOfRange(level) } errors.toList } } // 把错误类型转换成友好提示 def errorMessage(errors: List[ValidationError]): String = { errors.map { case InvalidRegistrationStatus(v) => s"registrationStatus只能是'a'、'b'或'c',当前值为$v" case LevelOutOfRange(v) => s"level必须在10到20之间,当前值为$v" }.mkString("; ") }
然后在路由中使用:
case updateUser @ PUT -> Root / "users" as user => { updateUser.req.as[UpdateUserRequest].flatMap { updateReq => updateReq.validate match { case Nil => // 业务逻辑处理 Ok(ApiResponse(200, true, "")) case errors => BadRequest(ApiResponse(400, false, errorMessage(errors))) } }.recover { case e: Exception => BadRequest(ApiResponse(400, false, s"请求格式错误:${e.getMessage}")) } }
说明
- 参数校验失败返回
400 Bad Request符合REST规范,也可以根据需求调整状态码 recover块专门处理JSON解析层面的错误,比如类型不匹配、必填字段缺失等情况- 自定义校验逻辑覆盖了业务规则约束,比单纯的JSON类型匹配更全面
内容的提问来源于stack exchange,提问作者Blankman
相关产品推荐
相关产品推荐

