如何使用 Scala Shapeless 在具有“大部分相同”字段的 类 之间进行转换
How to convert between to case classes with `mostly the same` fields using Scala Shapeless
这里我必须区分具有大部分相同字段的 classes。
final case class Id(id: String) // Param Class
final case class Age(id: Id, age: Int) // Param Class
final case class A(id: Id, data: Map[String, Any], age: Age) extends Presentable[A, APre] // Main Class 1
final case class APre(id: String, data: Map[String, Any], age: Int) // Main Class 2
这里 A
和 APre
是我的主要 classes.
现在我想使用 Shapeless 在这两个 class 之间进行转换,所以我编写了以下伪函数:
trait Presentable[E, P] {
def makePresentation[ET <: HList, PT <: HList](entity: E)(func : ET => PT)(implicit entGen: LabelledGeneric.Aux[E, ET], preGen: LabelledGeneric.Aux[P, PT]): P = {
val entList = entGen.to(entity)
preGen.from(func(entList))
}
}
这里func
是一个映射器,将A
的HList
映射到APre
的HList
(反之亦然)。
我想使用这样的功能:
val age = Age(Id("age_1"), 18)
val a = A(Id("id"), Map("tag1" -> "value1", "tag2" -> "value2"), age)
val pre = a.makePresentation { entList =>
entList.updateWith('id)((id: Id) => id.id).updateWith('age)((a: Age) => a.age)
}
这里我可以自己暗示映射函数。所以我可以转换任何两种情况 classes
所以问题是:
1. 如何使用 shapeless 转换这两个 classes?
2. 事实上,我有很多对 class,例如 A
到 APre
。所以我想要一个 trait
使用泛型来提取这个转换函数。这个函数怎么写?
免责声明:我是chimney的作者之一。
在 earlier releases of chimney 中,我们完全实现了您所要求的 - 使用 shapeless 在大多数相同的情况 类 之间进行转换。
我不建议手写它,因为有一些极端情况需要考虑(如果新对象缺少一些则创建值,转换更改的字段 type/name,Java Beans, value 类, etc),然后你必须想出如何配置它,所以如果你需要 shapeless-bases 解决方案,请查看 0.1.10.
中的代码
但是,从 0.2.0 开始,我们将实现重写为宏,因为如果您有更大的情况 类 进行转换(例如 12 个字段或更多),一些推导可能会计算几分钟(!),但没有希望除非我们放弃一些我们支持的案例,否则会有改进。
如果您只是在寻找一种处理转换的方法,那么请使用最新的烟囱,收工吧。
这里我必须区分具有大部分相同字段的 classes。
final case class Id(id: String) // Param Class
final case class Age(id: Id, age: Int) // Param Class
final case class A(id: Id, data: Map[String, Any], age: Age) extends Presentable[A, APre] // Main Class 1
final case class APre(id: String, data: Map[String, Any], age: Int) // Main Class 2
这里 A
和 APre
是我的主要 classes.
现在我想使用 Shapeless 在这两个 class 之间进行转换,所以我编写了以下伪函数:
trait Presentable[E, P] {
def makePresentation[ET <: HList, PT <: HList](entity: E)(func : ET => PT)(implicit entGen: LabelledGeneric.Aux[E, ET], preGen: LabelledGeneric.Aux[P, PT]): P = {
val entList = entGen.to(entity)
preGen.from(func(entList))
}
}
这里func
是一个映射器,将A
的HList
映射到APre
的HList
(反之亦然)。
我想使用这样的功能:
val age = Age(Id("age_1"), 18)
val a = A(Id("id"), Map("tag1" -> "value1", "tag2" -> "value2"), age)
val pre = a.makePresentation { entList =>
entList.updateWith('id)((id: Id) => id.id).updateWith('age)((a: Age) => a.age)
}
这里我可以自己暗示映射函数。所以我可以转换任何两种情况 classes
所以问题是:
1. 如何使用 shapeless 转换这两个 classes?
2. 事实上,我有很多对 class,例如 A
到 APre
。所以我想要一个 trait
使用泛型来提取这个转换函数。这个函数怎么写?
免责声明:我是chimney的作者之一。
在 earlier releases of chimney 中,我们完全实现了您所要求的 - 使用 shapeless 在大多数相同的情况 类 之间进行转换。
我不建议手写它,因为有一些极端情况需要考虑(如果新对象缺少一些则创建值,转换更改的字段 type/name,Java Beans, value 类, etc),然后你必须想出如何配置它,所以如果你需要 shapeless-bases 解决方案,请查看 0.1.10.
中的代码但是,从 0.2.0 开始,我们将实现重写为宏,因为如果您有更大的情况 类 进行转换(例如 12 个字段或更多),一些推导可能会计算几分钟(!),但没有希望除非我们放弃一些我们支持的案例,否则会有改进。
如果您只是在寻找一种处理转换的方法,那么请使用最新的烟囱,收工吧。