tethys icon indicating copy to clipboard operation
tethys copied to clipboard

Full Scala 3 derivation rework

Open goshacodes opened this issue 10 months ago • 0 comments

  • [x] Rewrited current derivation to make it simple and remove experimental staff. And everything gone to core module.
  • [x] Old derivation is fully deprecated. Old enum derivation is no longer compiles, since it can create problems on migration
  • [x] Instead of WriterBuilder[A] and ReaderBuilder[A] we now have JsonReader.ProductConfig[A] and JsonWriter.ProductConfig[A]. We can use inline given for configs.
case class Person(name: Int, age: String) derives JsonReader, JsonWriter

object Person:
  inline given JsonReader.ProductConfig[Person] = JsonReader.configure[Person]
    .extract(_.name).as[String]("abc")(identity)

  inline given JsonWriter.ProductConfig[Person] = JsonWriter.configure[Person]
    .rename(_.name)("abc")
    
  • [x] Made recursive derivation of readers и writers
  • [x] Including derivation of Or types in product for writers. .updatePartial is not added, you can use plain .update now.
case class Name(firstName: String, middleName: String, lastName: String)

case class Person(name: String | Name, age: String, any: Any) derives JsonWriter

object Person:
  inline given JsonWriter.ProductConfig[Person] = JsonWriter.configure[Person]
    .update(_.any) {
      case int: Int => int
      case str: String => str
      case other => other.toString
    }

// Name and String | Name would be autoderived for Person writer
  • [x] Simplified DependentField model Now you can build config like this
case class Person(name: String, age: Int, foo: Boolean, foo2: Long) derives JsonReader

object Person:
  inline given JsonReader.ProductConfig[PersonExtended] = JsonReader.configure[Person]
    .extract(_.foo).from(_.name).and(_.age).and(_.foo2).and[String]("bar")(...) // you can chain this a lot

  • [x] Added product auto combinator
case class Person(name: String, age: Int)

case class PersonExtended(person: Person, email: String) derives JsonReader

object Person:
  inline given JsonReader.ProductConfig[Person] = JsonReader.configure[PersonExtended]
    .extract(_.person).from[String]("name").and[Int]("age").product

  • [x] Add config for sum types. Lately fieldStyle и strict can be added there.
  • [x] Added discriminator for sum types. JsonReader can be derived with discriminator now.
sealed trait Choice(val discriminator: Int) derives JsonReader, JsonWriter:

object Choice:
  case class First(first: String) extends Choice(0)
  case class Second(second: Int) extends Choice(1)
  
  inline given JsonConfig[Choice] = JsonConfig.configure[Choice]
    .discriminateBy(_.discriminator)
  
(First("123"): Choice).asJson === {"discriminator": 0, "first": "123"}

{"discriminator": 0, "first": "123"}.jsonAs[Choice] === First("123")
  • [x] Added derivation for enums. Complex enums can be derived with JsonReader and JsonWriter.
  • [x] Basic enums can be derived with new interfaces OrdinalEnumJsonReader, OrdinalEnumJsonWriter, StringEnumJsonWriter, StringEnumJsonReader
enum Choice derives StringEnumJsonWriter, StringEnumJsonReader:
  case A, B
  
enum ComplexChoice(val choice: Choice) derives JsonReader, JsonWriter:
  case A(data: Int) extends ComplexChoice(Choice.A)
  case B(foo: String) extends ComplexChoice(Choice.B)
  
object CompleChoice:
  inline given JsonConfig[CompleChoice] = JsonConfig.configure[CompleChoice]
    .discriminateBy(_.choice)
  
  • [x] Improved validation of configuration. Check loops, existing fields, duplicate fields, etc

FieldStyle was copied to tethys package with new name JsonFieldStyle.

goshacodes avatar Apr 20 '24 18:04 goshacodes