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

Error is not correctly displayed for nested objects starting from 0.14.3 #2113

Closed
alycklama opened this issue Mar 17, 2023 · 5 comments
Closed
Labels

Comments

@alycklama
Copy link

I noticed that the error message is sometimes incorrect when decoding nested objects.

package org.my

import cats.implicits._
import io.circe.Decoder
import io.circe.parser.decode
import io.circe.generic.semiauto.deriveDecoder

object MyMain extends App {
  case class Location(city: String)
  case class Person(name: String, location: Location)

  val jsonString =
    """{
      | "name": "John",
      | "location": {
      | }
      |}""".stripMargin

  implicit val decoder: Decoder[Person] = deriveDecoder[Person]

  val result = decode[Person](jsonString)
  println(result)
  println(result.left.map(_.show))
}

For 0.14.2 it works as expected because it's clear where the missing property comes from (i.e. .location.city):

Left(DecodingFailure(Missing required field, List(DownField(city), DownField(location))))
Left(DecodingFailure at .location.city: Missing required field)

For 0.14.3 it doesn't work as expected as the root (.location) seems to be missing only in the .show:

Left(DecodingFailure(Missing required field, List(DownField(city), DownField(location))))
Left(DecodingFailure at .city: Missing required field)

For 0.14.4 and 0.14.5 the output is as follows where both miss the root object (i.e. .location):

Left(DecodingFailure at .city: Missing required field)
Left(DecodingFailure at .city: Missing required field)
@zarthross zarthross added the bug label Mar 29, 2023
@iyfedorov
Copy link
Contributor

#2138

@zorba128
Copy link

see also #2248

@zarthross
Copy link
Member

#2138 should fix this.

@alycklama
Copy link
Author

I can confirm this issue seems to be resolved.

However, I need to add an additional decoder for Location to make it work.

Updated Code

package org.my

import cats.implicits._
import io.circe._
import io.circe.generic.semiauto._
import io.circe.parser.decode

object Main extends App {
  case class Location(city: String)
  case class Person(name: String, location: Location)

  val jsonString =
    """{
      | "name": "John",
      | "location": {
      | }
      |}""".stripMargin

  implicit val locationDecoder: Decoder[Location] = deriveDecoder[Location]
  implicit val personDecoder: Decoder[Person] = deriveDecoder[Person]

  val result = decode[Person](jsonString)
  println(result)
  println(result.left.map(_.show))
}

Output

Left(DecodingFailure at .location.city: Missing required field)
Left(DecodingFailure at .location.city: Missing required field)

Ommitting Location Decoder

For some reason, it's no longer possible to derive nested case classes. You'll end up with the error below:

Could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[org.my.Main.Person]

I'll close this issue, as the issue has been resolved. It would be nice if the error was more precise, though. It's not the Person but the Location which could not be found.

@zarthross
Copy link
Member

zarthross commented Apr 22, 2024

The behavior is as expected. 'semi-auto' derivation should not do nested case classes.

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

4 participants