有没有一种很好的方法可以转换Scala case class
实例,例如
case class MyClass(param1: String, param2: String)
val x = MyClass("hello", "world")
进入某种映射,例如
getCCParams(x) returns "param1" -> "hello", "param2" -> "world"
适用于任何案例类,而不仅仅是预定义的类 . 我发现你可以通过编写一个询问底层Product类的方法来拉出case类名,例如:
def getCCName(caseobj: Product) = caseobj.productPrefix
getCCName(x) returns "MyClass"
所以我正在寻找类似的解决方案,但对于案例类字段 . 我想象一个解决方案可能不得不使用Java反射,但是如果案例类的底层实现发生变化,我讨厌在未来的Scala版本中编写一些内容 .
目前我正在使用Scala服务器并使用案例类定义协议及其所有消息和异常,因为它们是如此美观,简洁的构造 . 但是,我需要将它们转换为Java映射,以通过消息传递层发送以供任何客户端实现使用 . 我当前的实现只是分别为每个案例类定义一个翻译,但是找到一个通用的解决方案会很好 .
10 回答
详情:https://github.com/hank-whu/common4s
启动
Scala 2.13
,case class
es(作为Product的实现)提供了一个productElementNames方法,该方法返回其字段名称的迭代器 .通过使用productIterator获得的字段值压缩字段名称,我们通常可以获得关联的
Map
:这应该工作:
因为案例类扩展Product,所以可以简单地使用
.productIterator
来获取字段值:或者:
Product的一个优点是您不需要在字段上调用
setAccessible
来读取其值 . 另一个是productIterator不使用反射 .请注意,此示例适用于不扩展其他类且不在构造函数外声明字段的简单案例类 .
如果有人寻找递归版本,这里是@ Andrejs解决方案的修改:
它还将嵌套的case-classes扩展为任何嵌套级别的映射 .
如果您不关心将其作为通用函数,这是一个简单的变体:
你可以使用无形 .
让
定义LabelledGeneric表示
定义两个类型类以提供toMap方法
然后你可以像这样使用它 .
打印
对于嵌套的case类,(因此嵌套的map)检查another answer
来自解释器包的
ProductCompletion
解决方案:如果您碰巧使用Json4s,则可以执行以下操作:
我不知道好......但这似乎有用,至少对于这个非常基本的例子 . 它可能需要一些工作,但可能足以让你入门?基本上它从case类(或任何其他类:)过滤掉所有“已知”方法