scaladoobie

Reading data into custom case classes in Doobie


Let's say I have a case class X(id: Int, name: String, age: Int) and some function (in my case, withUniqueGeneratedKeys in doobie) that returns X. If I have already defined X I am good.

But in my case the core data structure is something like:

case class XData(name: String, age: Int)
case class MaterializedX(id: Int, element: XData)

And of course I could write a line like case class X(id: Int, name: String, age: Int) to create X but it would be duplication of logic - whenever something about XData changes, I'd have to change the code for X as well. Intuitively, it feels like there should be a way to derive X from XData and MaterializedX. This transformation might mean some code, but it would save me lots of future work because I have many item types beyond X.

How could this be done? Happy to hear other approaches.

I am using Scala 3.1.2 in case this matters. Thank you!

Edit: Changed title per helpful comment, to make this question easier to understand.


Solution

  • I think you should be more clear about the question, I mean what title says is almost completely different from your question description (and what you might be actually looking for). Anyway, in my assumptions, what you need is probably a custom Read[MaterializedX] and Write[MaterializedX], as follows:

    implicit val pointMaterializedX: Read[MaterializedX] =
      Read[(Int, String, Int)]
        .map { 
          case (id, name, age) => MaterializedX(id, XData(name, age)) 
        }
    
    implicit val pointWrite: Write[MaterializedX] =
      Write[(Int, String, Int)]
        .contramap { materializedX => 
          (materializedX.id, materializedX.element.name, materializedX.element.age)
        }
    

    More documentations here