Json.format, No unapply or unapplySeq function found for generics

3,980 views
Skip to first unread message

Zhao Hongwei

unread,
Dec 19, 2016, 1:08:30 AM12/19/16
to Play Framework
I extract a method for controller like:
def validateInput[A](json:JsValue)(func: A => Future[Result]):Future[Result]= {
 
implicit val format = Json.format[A]
  json
.validate[A].fold(
    errors
=> {
     
Future(BadRequest(JsError.toJson(errors)))
   
},
    validObj
=>
      func
(validObj)
 
)
}

when compiling the console shows:

[error] D:\program\ymgl\back\app\controllers\Security.scala:114: No unapply or unapplySeq function found
[error]     implicit val format = Json.format[A]
[error]                                      ^
[error] D:\program\ymgl\back\app\controllers\Security.scala:115: No Json deserializer found for type A. Try
 an implicit Reads or Format for this type.
[error]     json.validate[A].fold(
[error]                  ^
[error] two errors found

Does anyone can help me on this issue?

thanks,

henry

Greg Methvin

unread,
Dec 19, 2016, 1:20:48 AM12/19/16
to play-framework
It doesn't work because Json.format is a macro. It looks at the class at compile time and generates the code to serialize the JSON object to/from your class. Since A could be any type here this won't work.

What you probably want to do is accept an implicit Reads[A], which will allow json.validate[A] to work:
def validateInput[A: Reads](json:JsValue)(func: A => Future[Result]): Future[Result]
Then remove your Json.format[A] and declare your implicit Format for each type you want to serialize in its companion object, or wherever it's convenient for you.

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/f1c388a7-5516-47b3-b9e0-161f7bfe4d12%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Greg Methvin
Tech Lead - Play Framework

Greg Methvin

unread,
Dec 19, 2016, 1:25:40 AM12/19/16
to play-framework
Also there probably is some kind of performance hit you take from creating the Format every time. It's best to declare it as a val, e.g.

object User {
  implicit val format: Format[User] = Json.format[User]
}

henry z

unread,
Dec 19, 2016, 2:29:56 AM12/19/16
to Play Framework
Thanks Greg,  I done it under your suggestion and move the val into an object:

def validateInput[A : Reads ](json:JsValue)(func: A  => Future[Result]):Future[Result]= {
 
import models.JsonFormats._
  json
.validate[A].fold(

    errors
=> {
     
Future(BadRequest(JsError.toJson(errors)))
   
},
    validObj
=>
      func
(validObj)
 
)
}

JsonFormats
object JsonFormats {
 
import play.api.libs.json.Json

 
implicit val objectIdFormat = Json.format[ObjectId]

}

best regards,

henry z
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
--
Greg Methvin
Tech Lead - Play Framework

Greg Methvin

unread,
Dec 19, 2016, 2:43:30 AM12/19/16
to play-framework
The "import models.JsonFormats._" inside validateInput won't have any effect. The implicit Format has to be available at the call site of validateInput. I assume you already figured this out if it's working for you but just wanted to say that for the benefit of anyone else reading this.

To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/c0e04c6f-36f1-4535-8a4b-48f402665953%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages