Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detailed error on Enum reads in enumeratum-play-json #409

Open
Jenya95 opened this issue Nov 17, 2024 · 3 comments
Open

Detailed error on Enum reads in enumeratum-play-json #409

Jenya95 opened this issue Nov 17, 2024 · 3 comments

Comments

@Jenya95
Copy link

Jenya95 commented Nov 17, 2024

Error message that enumeratum produces could be enriched with list of valid enum values.

For example if there is enum

sealed trait Operand extends EnumEntry with Hyphencase with Lowercase
object Operand       extends enumeratum.Enum[Operand] with PlayJsonEnum[Operand] {
  val values = findValues

  case object Equals    extends Operand
  case object Gt        extends Operand
  case object GtEq      extends Operand
  case object Lt        extends Operand
  case object LtEq      extends Operand
}

and some case class

case class Foo(operand: Operand)

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

Then attempt to parse the string

test("parse json string into case class with enum") {
    val jsonString = "{\"operand\":\"unknown\"}"
    Json.parse(jsonString).as[Foo]
}

will print error

JsResultException(errors:List((/operand,List(JsonValidationError(List(error.expected.validenumvalue),WrappedArray())))))

But what if we will extend EnumFormats and let it print error with details like:

JsResultException(errors:List((/operand,List(JsonValidationError(List(error.expected.validenumvalue),WrappedArray(valid enum values are: (equals, gt, gt-eq, lt, lt-eq, not-equals, in, not-in), but provided: unknown))))))

with change like this at EnumFormats:140:

  private def readsKeyAndExtracts[A <: EnumEntry](
      @deprecatedName(Symbol("enum")) e: Enum[A]
  )(extract: String => Option[A]): KeyReads[A] = new KeyReads[A] {
    def readKey(s: String): JsResult[A] = extract(s) match {
      case Some(obj) => JsSuccess(obj)
      case None =>
        JsError(
          JsonValidationError(
            "error.expected.validenumvalue",
            s"valid enum values are: (${e.values.map(_.entryName).mkString(", ")}), but provided: $s"
          )
        )
    }
  }

It can be disabled by default, configurable by some flag in trait PlayJsonEnum.

Does it make sense to implement?

@lloydmeta
Copy link
Owner

I think this sounds like a nice enhancement.

@lloydmeta
Copy link
Owner

You should fork and push the branch to your fork then send a PR here.

@Jenya95
Copy link
Author

Jenya95 commented Nov 24, 2024

@lloydmeta PR at #411

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants