jack miao
jack miao

Reputation: 1498

What would be the best way in scala to convert between case classes?

I have a model class im getting back from an api inside my servcie, and when I return it to some client I want to use my own model to keep it simpler and cleaner for the client.

example :

case class ReturnedModel(succeed: Option[String], reason: Reason, transactionId: List[Int], opId: Option[Int])

case class MyReturnedModel(reason: String)

I might need to do more of those in the future so I thought maybe there is a best practice to do it that I dont know of, thanks!

Upvotes: 0

Views: 1285

Answers (3)

David Weber
David Weber

Reputation: 1995

You can use a companion object with a custom "apply" method:

case class MyReturnedModel(reason: String)

object MyReturnedModel {
  def apply(mod: ReturnedModel) = MyReturnedModel(mod.reason.toString)
}

val data: ReturnedModel = ... // Some instance of ReturnedModel
val mr = MyReturnModel(data)

Just note that the case class and its companion object need to be in the same file for this to work.

Upvotes: 1

Tyler
Tyler

Reputation: 18187

If you have access to change the ReturnedModel, you could use traits like @pedrofurla has demonstrated.

If you are unable to modify the ReturnedModel, you could declare an implicit function to convert all instance of ReturnedModel to MyReturnedModel like this:

implicit def returnedModelToMyModel(returnedModel: ReturnedModel): MyReturnedModel = {

  // Have some logic to convert their model to your model
  MyReturnedModel(returnedModel.reason.toString)

}

Then whenever you get a ReturnedModel from the API, you can use it anywhere you are expecting an instance of MyReturnedModel:

def doWork(myReturnedModel: MyReturnedModel) = { /* Logic that needs and instance of MyReturnedModel */ }

// Grab an instance of ReturnModel from the API
val returned: ReturnedModel = ???

// Will get converted when you need it to be an instance of MyReturnedModel
doWork(returned)

The compiler will try to preform implicit conversions when it finds that the type you have passed is not correct, at which point it will look for an implicit conversion to satisfy the type conversion.

Upvotes: 0

pedrofurla
pedrofurla

Reputation: 12783

Depending on your use case:

sealed trait IKnowAReason { def reason:String }

case class ReturnedModel(succeed: Option[String], reason: Reason,
  transactionId: List[Int], opId: Option[Int]) extends IKnowAReason

Now replace uses of MyReturnedModel with IKnowAReason. Notice the sealed, it will ensure that there are no other implementations of IKnowAReason outside the same source file.

Upvotes: 0

Related Questions