简体   繁体   中英

How to improve the error message readability returned from JsError.toFlatJson or JsError.toJson in Play framework 2.x?

I have a JSON REST API server built with Play framework v2.3 with scala, and I have controller's action like this for example:

  def register = Action.async(BodyParsers.parse.json) { implicit request => 
      request.body.validate[Register].fold(
        errors => Future.successful(BadRequest(JsError.toFlatJson(errors))),
        register => {
            // do something here if no error...
          }
      )
    }

For simplicity, I handle the validation error with JsError.toFlatJson (note: JsError.toFlatJson is deprecated in newer Play, the replacement is JsError.toJson ).

The problem is the json result have cryptic message like:

{"obj.person.email":[{"msg":"error.email","args":[]}]}

Above json indicates the person's email is invalid.

Is there a way to convert the error json result into more readable message?

I don't want the client apps should doing the mapping/conversion of the obj.person.email or error.email . I prefer the server does it before returning the json to the client apps.

Part of your problem can be solved by defining custom errors messages in your class' Reads combinator with orElse :

case Point(x: Int, y: Int)

object Point {
    implicit val pointReads: Reads[Point] = (
        (__ \ "x").read[Int].orElse(Reads(_ => JsError("Could not parse given x value.")))
        (__ \ "y").read[Int].orElse(Reads(_ => JsError("Could not parse given y value.")))
    )(Point.apply _)
}

Given some invalid JSON for this class you'll now get custom error messages for validation problems:

scala> val incorrectJson = Json.parse("""{"y": 1}""")
incorrectJson: play.api.libs.json.JsValue = {"y":1}

scala> val validationResult = incorrectJson.validate[Point]
validationResult: play.api.libs.json.JsResult[playground.Point] = JsError(List((/x,List(ValidationError(List(Could not read the point's x value.),WrappedArray())))))

scala> validationResult.fold(error => { println(JsError.toJson(error)) }, a => { a })
{"obj.x":[{"msg":["Could not read the point's x value."],"args":[]}]}

In order to change the obj.x identifier you'll have to post-process the returned JsValue yourself because it's derived from the implementation of JsPath .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM