tethys icon indicating copy to clipboard operation
tethys copied to clipboard

Cannot override reader builder of Option field

Open anton0xf opened this issue 1 year ago • 2 comments

I can read field value from one of two JSON-fields with code like this (and it works well):

import tethys._
import tethys.jackson._
import tethys.derivation.builder._
import tethys.derivation.semiauto._

case class Foo(a: Int)

implicit val fooReader: JsonReader[Foo] = jsonReader[Foo] {
  ReaderBuilder[Foo]
    .extract(_.a)
    .from("a".as[Option[Int]], "b".as[Option[Int]])((a, b) =>
      a.orElse(b)
        .getOrElse(throw new RuntimeException("cannot find 'a' or 'b'"))
    )
}

println("""{"b": 2}""".jsonAs[Foo]) 
// => Right(Foo(2))

Playground

But the same approach doesn't work if a is Option:

// same imports
case class Foo(a: Option[Int])

implicit val fooReader: JsonReader[Foo] = jsonReader[Foo] {
  ReaderBuilder[Foo]
    .extract(_.a)
    .from("a".as[Option[Int]], "b".as[Option[Int]])((a, b) => a.orElse(b))
}

println("""{"b": 2}""".jsonAs[Foo]) 
// => Right(Foo(None)) 
// but expected
// => Right(Foo(2))

Playground

Is it a bug or my misunderstanding?

I tested it on 0.28.3 and some older versions

anton0xf avatar Jun 18 '24 10:06 anton0xf

It is even works well if I don't mention "a" fielld:

case class Foo(a: Option[Int])

implicit val fooReader: JsonReader[Foo] = jsonReader[Foo] {
  ReaderBuilder[Foo]
    .extract(_.a)
    .from("c".as[Option[Int]], "b".as[Option[Int]])((c, b) => c.orElse(b))
}

println("""{"b": 2}""".jsonAs[Foo]) // => Right(Foo(Some(2)))
println("""{"c": 2}""".jsonAs[Foo]) // => Right(Foo(Some(2)))

Playground

anton0xf avatar Jun 18 '24 10:06 anton0xf

Thanks for reporting! That's indeed looks like a bug

dos65 avatar Jun 27 '24 11:06 dos65

Considering fix only for scala 3

goshacodes avatar Feb 15 '25 08:02 goshacodes