scalareflectionshapeless

scala case class conversation for DTO(shapeless)


I want convert case class UserDTO to case class User I find solution in shapeless case class conversion

class SameFieldConverter[T] {
def apply[S, SR <: HList, TR <: HList, MR <: HList, IR <: HList](s: S)(implicit
  genS: LabelledGeneric.Aux[S, SR],
  genT: LabelledGeneric.Aux[T, TR],
  merger: Merger.Aux[SR, HNil, MR],
  intersection: Intersection.Aux[MR, TR, IR],
  align: Align[IR, TR]) = genT.from(intersection(merger(genS.to(s), HNil)))

but i have problem with diffirent field, example in UserDTO i have field name, surname, but in User i have fullName.

  case class UserDTO(name:String, surname:String, age:Int){
    def toDomain:User = User(name + surname, age)
  }
  case class User(fullName:String, age:Int)

Also I have problem with diffirent field names exaples name -> last name

case class UserDTO(name:String, surname:String, age:Int)
case class User(firstName:String, surname:String, age:Int)

I think about solution like in a quill alias("name", _.surname), but i have small brain. I was also thinking of looking into the use of scala reflection API


Solution

  • If you just want to convert from a case class to another case class where both have same or similar fields, I think shapeless is an overkill. I would choose chimney for something like that. The code should look like

    libraryDependencies += "io.scalaland" %% "chimney" % "1.7.3"
    
    import io.scalaland.chimney.dsl._
    
    case class UserDTO(name:String, surname:String, age:Int)
    case class User(firstName:String, surname:String, age:Int)
    
    class Transformer {
      def fromUserDtoToUser(userDTO: UserDTO): User = {
        userDTO
          .into[User]
          .withFieldComputed(_.firstName, _.name) // here is the mapping between fields with different names
          .transform
      }
    }
    

    and a dummy main method should look like

    object Main {
      def main(args: Array[String]): Unit = {
        val transformer = new Transformer
        val userDTO = UserDTO("john", "doe", 30)
        val user = transformer.fromUserDtoToUser(userDTO)
        println(userDTO)
        println(user)
      }
    }
    

    The output will be

    UserDTO(     name = john, surname = doe, age = 30)
    User(   firstName = john, surname = doe, age = 30)