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

Invalid pathToRoot for missing required field validation error #2248

Open
zorba128 opened this issue Apr 11, 2024 · 2 comments
Open

Invalid pathToRoot for missing required field validation error #2248

zorba128 opened this issue Apr 11, 2024 · 2 comments
Labels

Comments

@zorba128
Copy link

zorba128 commented Apr 11, 2024

Validation error reports invalid path (one segment missing) for missing required field validation error.
See code below to compare how it looks like for invalid field type vs missing field.

  sealed trait A

  case class AA(a: Int) extends A

  case class X(a1: AA, a2: A)

  implicit val aaCodec: Codec[AA] = io.circe.generic.semiauto.deriveCodec
  implicit val aCodec: Codec[A] = io.circe.generic.semiauto.deriveCodec
  implicit val xCodec: Codec[X] = io.circe.generic.semiauto.deriveCodec

  println(X(AA(1), AA(2)).asJson.noSpaces) //{"a1":{"a":1},"a2":{"AA":{"a":2}}}

  // similar input; in first `a1.a` has invalid type, in second `a1.a` is missing
  val input1 = json"""{"a1":{"a":true},"a2":{"AA":{"a":2}}}""" // invalid type
  val input2 = json"""{"a1":{},"a2":{"AA":{"a":2}}}""" // missing required field
  println(input1.as[X]) // Left(DecodingFailure at .a1.a: Int)
  println(input2.as[X]) // Left(DecodingFailure at .a: Missing required field) - path should be as above

  // same here, just with additional nest level
  val input3 = json"""{"a1":{"a":1},"a2":{"AA":{"a":true}}}""" // invalid type
  val input4 = json"""{"a1":{"a":1},"a2":{"AA":{}}}""" // missing required field
  println(input3.as[X]) // Left(DecodingFailure at .a2.AA.a: Int)
  println(input4.as[X]) // Left(DecodingFailure at .a2.a: Missing required field)  - path should be as above
@zorba128
Copy link
Author

It seems that cursor history in the DecodingFailure is fine, its pathToRoot which is wrong. See another simplified sample below

  @JsonCodec case class Z(z: Int)
  @JsonCodec case class Y(y: Z)
  @JsonCodec case class X(x: Y)

  println(X(Y(Z(1))).asJson.noSpaces) // {"x":{"y":{"z":1}}}
  println(json"""{"x":{"y":{}}}""".as[X]) //Left(DecodingFailure at .x.z: Missing required field)

  // clears pathToRoot using path from cursor history
  def patch[T](a: Either[DecodingFailure, T]) = a.swap.map(a => DecodingFailure(a.reason, a.history)).swap

  println(patch(json"""{"x":{"y":{}}}""".as[X])) //Left(DecodingFailure at .x.y.z: Missing required field)

@zarthross
Copy link
Member

#2138 I believe fixes this.

@zarthross zarthross added the bug label Apr 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants