We have the following example and it seems that extractors do not work while converting Json to case class.
import play.api.libs.json.Reads._
import play.api.libs.json._
import play.api.libs.json.Format.GenericFormat
val json: JsValue = Json.parse("""
{
"firstName" : "John",
"lastName" : "Doe"
}
""")
trait BasePublicForm {
def firstName: String
def lastName: String
}
case class CustomerPublicForm(firstName: String, lastName: String) extends BasePublicForm
case class LeadPublicForm(firstName: String, lastName: String ) extends BasePublicForm
object CustomerPublicForm {
implicit val writesPublicLeadFormRequest: Writes[CustomerPublicForm] = Json.writes[CustomerPublicForm]
implicit val readsPublicLeadFormRequest: Reads[CustomerPublicForm] = Json.reads[CustomerPublicForm]
def apply(firstName: String, lastName: String): CustomerPublicForm = {
if(firstName.equalsIgnoreCase("John")) {
throw new Exception("John Exception")
}
new CustomerPublicForm(firstName, lastName)
}
}
object LeadPublicForm {
def apply(firstName: String, lastName: String): LeadPublicForm = {
new LeadPublicForm(firstName, lastName)
}
}
val s = json.validate[CustomerPublicForm] match {
case JsSuccess(form, _) => {
form
// do something with place
}
case e: JsError => {
// error handling flow
throw new Exception("Error")
}
}
s
Link -> https://scastie.scala-lang.org/eZrHTOVkQvSUJmoAJMTXfQ
Any ideas why it does not return Exception
as expected?
CodePudding user response:
The code doesn't throw an Exception
(which is probably not a good idea anyway), as the json
input is valid and so .validate
returns CustomerPublicForm(John,Doe)
CodePudding user response:
The Json.reads[CustomerPublicForm]
seems to be circumventing your apply
method.
I'm not sure of the exact details of Play's macro Reads generation, but it's probably just going straight for your class constructor rather than the apply
method. Since the apply
method you wrote has the same signature as the existing constructor, you'd be better off if you moved the validation (exception throwing) logic into the constructor and just removing the custom apply
.
Alternatively you could make a custom apply
with a different signature (not that it makes sense in this case, but I'm speaking generally here), and then using non-macro code to implement the Reads for that class.