i use shapeless for case class conversion, i have a 2 case class:
import shapeless._
case class Foo(id: Int, name: String)
case class Bar(id: Int, name: String, price: Double)
val fooGen = Generic[Foo]
val barGen = Generic[Bar]
val foo = Foo(1, "foo")
val fooRepr = fooGen.to(foo)
val additional = fooRepr :+ 1.0
val bar = barGen.from(additional)
This works fine, but when i try convert Bar to Foo
fooGen.from(barGen.to(bar))
i get an error:
found : main.barGen.Repr
[error] (which expands to) shapeless.::[Int,shapeless.:: [String,shapeless.::[Double,shapeless.HNil]]]
[error] required: main.fooGen.Repr
[error] (which expands to) shapeless.::[Int,shapeless.::[String,shapeless.HNil]]
[error] println(fooGen.from(barGen.to(bar)))
Is it possible convert one case class where more fields than in another?
Similar to how you adjust the HList representation of Foo, by adding an element, you'd have to adjust the HList representation of Bar as well, by removing the extra element:
fooGen.from(barGen.to(bar).take(2))
take takes a Nat argument, and this line of code uses the implicit conversion from an Int literal to a Nat type-level natural number.
You can find other methods available on HLists in shapeless.syntax.hlists.scala.
My answer is based on a previous answer by Travis Brown, for a somewhat similar question.
import shapeless._, ops.hlist._, ops.record._
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)))
}
// defined class SameFieldConverter
def convertTo[T] = new SameFieldConverter[T]
//defined function convertTo
case class Foo(one: String, two: Int, three: Boolean)
// defined class Foo
case class Bar(three: Boolean, one: String)
// defined class Bar
convertTo[Bar](Foo("One", 2, false))
// res26: Bar = Bar(false, "One")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With