Reputation: 71
Was following Play Frameworks's Scala Json api Docs when got this error :
value read is not a member of play.api.libs.json.JsValue
My Imports are :
import play.api.libs.json._ // JSON library
import play.api.libs.json.Reads._ //custom validation helpers
import play.api.libs.functional.syntax._ // Combinator syntax
and method throwing error is :
def callSearchRoleRowInRoleService = Action(parse.json) {
implicit request =>
var rolejson = request.body
val roleId = (rolejson \ "roleId").read[Int]
val shortDescription : Reads[String]= (rolejson \ "shortDescription").read[String]
val description = (rolejson \ "description").read[String]
val activationDate = (rolejson \ "activationDate").read[java.sql.Date]
val deactivationDate = (rolejson \ "deactivationDate").read[java.sql.Date]
}
Working perfectly fine without read method
Upvotes: 0
Views: 2158
Reputation: 55569
You really ought to deserialize your data to a case class. read[A]
is a method on JsPath
in order to create Reads[A]
to combine into a larger Reads
object. As @drexin mentioned, you're probably looking for as[A]
, however it is not a safe operation. If a single as
fails, it throws an exception, which in your controller logic will result in a internal server error with little information to help the user.
You can construct Reads
for a case class like this:
case class Role(id: Int, short: String, description: String, activation: java.sql.Date, deactivation: java.sql.Date)
object Role {
implicit val reads: Reads[Role] = (
(JsPath \ "roleId").read[Int] and
(JsPath \ "shortDescription").read[String] and
(JsPath \ "description").read[String] and
(JsPath \ "activationDate").read[java.sql.Date] and
(JsPath \ "deactivationDate").read[java.sql.Date]
)(Role.apply _)
}
Then your controller function would look more like this:
def callSearchRoleRowInRoleService = Action(parse.json) { implicit request =>
request.body.validate[Role].fold(
errors => { // handle validation errors, return some error message? },
role => { // do something with the `role` to product a `Result` }
)
}
The advantage of using validate
is that all of the validation errors will be accumulated so they can be handled all at once, without throwing exceptions.
And because someone else is just bound to mention it, for simple case classes (like the one above), you can skip the combinators and use the macro:
implicit val reads = Json.reads[Role]
Upvotes: 2
Reputation: 24423
You only have to use read[A]
if you are using combinators to create a Reads[A]
. The method you are looking for is as[A]
.
Upvotes: 1