Home > Blockchain >  Extractor does not return exception
Extractor does not return exception

Time:12-01

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.

  • Related