Учитывая пару классов case, Source
и Target
, которые имеют вложенные классы case, и на каждом уровне вложенности поля в Target
являются невыровненными подмножествами полей в Source
, есть ли способ написать универсальное преобразование на основе Shapeless из Source
до Target
?
Например, для следующих классов Internal
и External
:
object Internal {
case class User(
firstName: String,
lastName: String,
isAdmin: Boolean,
address: Address
)
case class Address(
street: String,
country: String,
blacklisted: Boolean
)
}
object External {
// Note that isAdmin is missing and the fields are jumbled
case class User(
lastName: String,
firstName: String,
address: Address
)
// blacklisted is gone
case class Address(
street: String,
country: String
)
}
Я хотел бы иметь возможность сделать что-то вроде
val internalUser = Internal.User(
firstName = "Joe",
lastName = "Blow",
isAdmin = false,
address = Internal.Address(
street = "Sesame",
country = "U-S-A",
blacklisted = false
)
)
val externalUser = Transform.into[External.User](internalUser)
У меня есть какой-то код, который заботится о выборе подмножества и выравнивании полей, но часть рекурсии немного сложнее:
import shapeless._, ops.hlist.Align, ops.hlist.SelectAll, SelectAll._
class Transform[T] {
// The fun stuff. Given an S, returns a T, if S has the right (subset of) fields
def apply[S, SR <: HList, TR <: HList](s: S)(
implicit
genS: LabelledGeneric.Aux[S, SR],
genT: LabelledGeneric.Aux[T, TR],
selectAll: SelectAll[SR, TR],
align: Align[SelectAll[SR, TR]#Out, TR]): T =
genT.from(align(selectAll(genS.to(s))))
}
object Transform {
// Convenience method for building an instance of `Transform`
def into[T] = new Transform[T]
}
Я рассмотрел этот вопрос SO, но ответ не учитывает тот факт, что поля являются невыровненными подмножествами другого.