使用 Shapeless 将嵌套案例类转换为嵌套映射

2023-12-24

我正在尝试使用 Shapeless 解决 [this][1] 问题,总而言之,它是将嵌套案例类转换为 Map[String,Any],以下是示例:

case class Person(name:String, address:Address)
case class Address(street:String, zip:Int)

val p = Person("Tom", Address("Jefferson st", 10000))

目标是转换p至以下:

Map("name" -> "Tom", "address" -> Map("street" -> "Jefferson st", "zip" -> 10000))

我正在尝试使用 Shapeless 来做到这一点LabelledGeneric,这是我到目前为止所拥有的:

import shapeless._
import record._, syntax.singleton._
import ops.record._
import shapeless.ops.record._

def writer[T,A<:HList,H<:HList](t:T)
(implicit lGeneric:LabelledGeneric.Aux[T,A],
 kys:Keys.Aux[A,H],
 vls:Values[A]) = {
    val tGen = lGeneric.to(t)
    val keys = Keys[lGeneric.Repr].apply
    val values = Values[lGeneric.Repr].apply(tGen)
    println(keys)
    println(values)
  }

我试图让递归编写器检查每个值并尝试为值中的每个元素创建映射。上面的代码工作正常,但是当我想迭代时values使用示例 Poly,使用以下代码我得到了这些错误。

values.map(identity)
//or
tGen.map(identity)

Error:(75, 19) could not find implicit value for parameter mapper: shapeless.ops.hlist.FlatMapper[shapeless.poly.identity.type,vls.Out]
    values.flatMap(identity)
                  ^
Error:(75, 19) not enough arguments for method flatMap: (implicit mapper: shapeless.ops.hlist.FlatMapper[shapeless.poly.identity.type,vls.Out])mapper.Out.
Unspecified value parameter mapper.
    values.flatMap(identity)
                  ^

我不知道为什么我会收到这个错误。我也很高兴知道是否有一种更简单的方法可以使用 Shapeless 来完成整个事情。 [1]:Scala 宏用于嵌套案例类到 Map 和其他方式 https://stackoverflow.com/questions/31528379/scala-macros-for-nested-case-classes-to-map-and-other-way-around


任何时候你想执行类似的操作flatMap on an HList如果其类型不是静态已知的,则您需要提供证据(以隐式参数的形式)来证明该操作实际上可用于该类型。这就是编译器抱怨缺少的原因FlatMapper实例——它不知道如何flatMap(identity)超过任意的HList没有他们。

完成此类事情的一种更简洁的方法是定义自定义类型类。 Shapeless 已经提供了ToMap https://github.com/milessabin/shapeless/blob/698daa1e08ced007c14a9c5303ba094815ad6f1c/core/src/main/scala/shapeless/ops/records.scala#L339记录的类型类,我们可以将其作为起点,尽管它没有提供您正在寻找的确切内容(它不能在嵌套案例类上递归地工作)。

我们可以写如下内容:

import shapeless._, labelled.FieldType, record._

trait ToMapRec[L <: HList] { def apply(l: L): Map[String, Any] }

现在我们需要提供三种情况的实例。第一种情况是基本情况——空记录——它由hnilToMapRec below.

第二种情况是我们知道如何转换记录的尾部,并且我们知道头是我们也可以递归转换的情况(hconsToMapRec0 here).

最后的情况类似,但对于没有的头ToMapRec实例(hconsToMapRec1)。请注意,我们需要使用LowPriority特征,以​​确保此实例的优先级正确hconsToMapRec0—如果我们不这样做,两者将具有相同的优先级,并且我们会收到有关不明确实例的错误。

trait LowPriorityToMapRec {
  implicit def hconsToMapRec1[K <: Symbol, V, T <: HList](implicit
    wit: Witness.Aux[K],
    tmrT: ToMapRec[T]
  ): ToMapRec[FieldType[K, V] :: T] = new ToMapRec[FieldType[K, V] :: T] {
    def apply(l: FieldType[K, V] :: T): Map[String, Any] =
      tmrT(l.tail) + (wit.value.name -> l.head)
  }
}

object ToMapRec extends LowPriorityToMapRec {
  implicit val hnilToMapRec: ToMapRec[HNil] = new ToMapRec[HNil] {
    def apply(l: HNil): Map[String, Any] = Map.empty
  }

  implicit def hconsToMapRec0[K <: Symbol, V, R <: HList, T <: HList](implicit
    wit: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, R],
    tmrH: ToMapRec[R],
    tmrT: ToMapRec[T]
  ): ToMapRec[FieldType[K, V] :: T] = new ToMapRec[FieldType[K, V] :: T] {
    def apply(l: FieldType[K, V] :: T): Map[String, Any] =
      tmrT(l.tail) + (wit.value.name -> tmrH(gen.to(l.head)))
  }
}

最后,为了方便起见,我们提供了一些语法:

implicit class ToMapRecOps[A](val a: A) extends AnyVal {
  def toMapRec[L <: HList](implicit
    gen: LabelledGeneric.Aux[A, L],
    tmr: ToMapRec[L]
  ): Map[String, Any] = tmr(gen.to(a))
}

然后我们可以证明它是有效的:

scala> p.toMapRec
res0: Map[String,Any] = Map(address -> Map(zip -> 10000, street -> Jefferson st), name -> Tom)

请注意,这不适用于嵌套案例类位于列表、元组等中的类型,但您可以非常简单地将其扩展到这些案例。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Shapeless 将嵌套案例类转换为嵌套映射 的相关文章

  • Scala Stream 按需要调用(惰性)与按名称调用

    所以我知道按需要呼叫只是按名称呼叫的记忆版本 在 Martin Odersky 在 Coursera 上的 FP 课程中 第 7 3 讲 惰性评估 中 他提到如果 Streams 是使用按名称调用来实现的 那么它可能会导致计算复杂性的激增
  • 如何更改 SBT 命令内的设置?

    我想要一个命令publish snapshot这将运行publish修改后的任务version设置 该设置将在执行命令时计算 我想出了如何获取当前值version内部命令 以及Project runTask task scope 似乎是调用
  • Scala 2.10、Double.isNaN 和拳击

    在 Scala 2 10 中 是someDouble isNaN预计装箱 运行我的代码调用 isNaN通过反编译器 我仍然看到对double2Double在我的代码中 鉴于新的AnyVal在 2 10 中工作 我希望它不会比java lan
  • scala.collection.breakOut 与视图

    这个答案 https stackoverflow com a 1716558 936869描述如何scala collection breakOut可用于防止创建浪费的中间集合 例如 这里我们创建一个中间体Seq String String
  • 将列表拆分为多个具有固定元素数量的列表

    如何将元素列表拆分为最多包含 N 个项目的列表 例如 给定一个包含 7 个元素的列表 创建 4 个组 最后一组可能包含较少的元素 split List 1 2 3 4 5 6 seven 4 gt List List 1 2 3 4 Lis
  • 为什么调用 take() 方法时 Slick 会生成子查询

    I use Slick http slick typesafe com 1 0 0 RC1 我对表对象有这样的定义 object ProductTable extends Table Int String String String Dou
  • Liftweb 环境中的后台任务

    我必须编写守护进程 并且我想使用模型来连接到数据库和一些有用的 Lift 类 是否可以运行 Rails 的 rake 任务的模拟 Scala 社区组上也有类似的问题 答案是使用Actors来做后台处理
  • Scala:在运行时获取 mixin 接口

    我需要在运行时从给定的类获取所有接口 全部加载在类加载器中 例如 如果一个类是这样声明的 trait B trait C trait D class A extends B with C with D 我想在运行时获取这些信息 A 取决于
  • 了解如何使用 apply 和 unappy

    我试图更好地理解 的正确用法apply and unapply方法 考虑到我们想要序列化和反序列化的对象 这是正确的用法吗 即斯卡拉方式 的使用apply and unapply case class Foo object Foo appl
  • 哪些 ORM 与 Scala 配合得很好? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 重塑案例类构造函数?

    试图找到一种方法来 重塑 案例构造函数以填充某些默认值 以下情况可能吗 def reshape T R1 lt HList R2 lt HList h R1 R2 gt T example case class MyClass a Doub
  • 如何使用 apply/unapply 方法重现案例类行为?

    我尝试用普通类和伴生对象替换案例类 但突然出现类型错误 编译良好的代码 综合示例 trait Elem A B def C other Elem C A Elem C B other match case Chain head tail g
  • 将 Scala 库转换为 DLL (.NET)

    我正在尝试从 scala 类创建一个 Dll 我将 IntelliJ 与 SBT 一起使用 我已经找到了一种使用 ikvm converter 将 jar 文件转换为 Dll 的方法 现在的问题是 当我在 SBT 下使用 package 从
  • 逆变方法参数类型

    wiki 逆变方法参数类型 https en wikipedia org wiki Covariance and contravariance 28computer science 29 Contravariant method argum
  • Scala Array.apply 有何魔力

    来自 scala 2 10 4 的 array scala Array定义为 final class Array T length Int extends java io Serializable with java lang Clonea
  • 使用 Akka 玩 2.5 - 找不到参数超时的隐式值:akka.util.Timeout

    我正在尝试使用 Play 2 5 测试 Akka 但遇到了一个似乎无法解决的编译错误 我正在关注 Play 文档中的此页面 https playframework com documentation 2 5 x ScalaAkka http
  • 阶乘的 Scala 排列

    我怎样才能找到n Scala 中某些字母的排列 Scala 2 9 RC1 scala gt abc permutations toList res58 List String List abc acb bac bca cab cba
  • Scala:类似 Option (Some, None) 但具有三种状态:Some、None、Unknown

    我需要返回值 当有人询问值时 告诉他们以下三件事之一 这是值 没有价值 我们没有关于该值的信息 未知 情况 2 与情况 3 略有不同 示例 val radio car radioType 我们知道该值 返回无线电类型 例如 pioneer
  • 使用 Spark DataFrame 获取组后所有组的 TopN

    我有一个 Spark SQL DataFrame user1 item1 rating1 user1 item2 rating2 user1 item3 rating3 user2 item1 rating4 如何按用户分组然后返回TopN
  • 类型级编程有哪些示例? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我不明白 类型级编程 是什么意思 也无法使用Google找到合适的解释 有人可以提供一个演示类型级编程的示例吗 范式的解释和 或定义将

随机推荐

  • 错误:pycryptodome 构建轮子失败

    我试图安装pycryptodome python jose cryptodome using pip within 蟒蛇3环境 我收到这个错误 ERROR Failed building wheel for pycryptodome 我已经
  • 如何使用 AWS SageMaker Notebook 实例部署预训练模型?

    我有一个预先训练的模型 正在从 S3 存储桶加载到 AWS SageMaker 笔记本实例中 并在提供用于从 S3 存储桶进行预测的测试图像后 它会根据需要为我提供准确的结果 我想部署它 以便拥有一个端点 可以进一步与 AWS Lambda
  • QGlWidget全屏无菜单

    我有一个应用程序 它是一个单独的 QGlwidget 并在需要时创建右键单击 QMenu 数据在重写的paintEvent 中绘制 但在全屏模式下 不会显示菜单 我最好将 QGraphicsScene 作为父窗口 将 QGlWidget 作
  • C# MySQL 连接器 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我应该为 MySQL 构建自己的包装类 还是应该使用下载 Visual Studio 的可安装 MySQL 插件之一来提供帮助 我的应用程
  • 未捕获的引用错误:未定义刷新

    您好 我正在尝试以 content id postlist 样式获取我的帖子 并且我已经准备好需要刷新页面 刷新 但由于某种原因 我收到 刷新未定义 错误 并且我显示的帖子没有样式 document on pagebeforeshow bl
  • 保存未公开其关系的外键属性的实体时发生错误

    我有一个简单的代码实体框架 EF v4 1代码先 PasmISOContext db new PasmISOContext var user new User user CreationDate DateTime Now user Last
  • _DllMain@12 已定义

    我尝试从 mDNSResponder 107 6 tar gz 存档构建子项目 ExplorerPlugin 但 收到下一个链接错误 uafxcwd lib dllmodul obj 错误 LNK2005 DllMain 12 已定义 怎么
  • DataContractSerializer 与 XmlSerializer:每个序列化器的优缺点

    我的桌面应用程序使用序列化对象XmlSerializer 有人建议我利用DataContractSerializer反而 哪些场景下应该使用DataContractSerializer 非常感谢 评论 1 输出的XML文件存储在本地 没有其
  • junit5 给出扩展之间的依赖关系

    我刚刚开始编写一些 junit5 测试和扩展 我很快就遇到了我认为的问题 我如何告诉 junit5ExtensionB需要ExtensionA在场 例如我有一个 基本 扩展ExtensionA它启动一个数据库并进行一些初始化 这对于一些测试
  • 在 testflightapp.com 上哪里可以看到 TFLog 输出?

    我在用着TFLog在我的 iPhone 应用程序中 但是在哪里https testflightapp com https testflightapp com我可以查看输出吗 我只是通过反复试验以及在 TestFlight 网站上多次点击才发
  • Gerrit:添加/提交到本地 git 存储库后,尝试推送到远程时收到:[远程拒绝](未进行任何更改)

    以下是尝试推送到远程 git 存储库时的输出 Counting objects 28 done Delta compression using up to 8 threads Compressing objects 100 26 26 do
  • 房间类型地图转换器

    你会如何为 Map 编写 TypeConverter 我的方法是由 Moshi 来做 class Converters val moshi Moshi Builder add KotlinJsonAdapterFactory build v
  • curl_multi_getcontent 返回空字符串

    这个问题非常类似于PHPcurl multi gecontent 返回 null https stackoverflow com questions 18796693 php curl multi getcontent returns nu
  • qnamaker 与 LUIS

    我正在探索微软的服务 路易斯引起了我的注意 将其添加到 QNAmaker 机器人会有好处吗 机器人基本上会尽可能准确地回答问题 没有别的 只是来自知识库的纯粹答案 我还需要添加 LUIS 吗 不 您不需要 LUIS 即可让 QnA 制作者回
  • 是否可以使用会员 API 更改用户名

    我正在 ASP NET 中使用默认的 sql 成员资格提供程序 并且我想提供一个页面来更改用户的用户名 我相信我确信我可以使用自定义提供程序来完成此操作 但是可以使用默认提供程序来完成此操作吗 我的问题的第二部分是 我是否应该允许用户在创建
  • C++中继承模板类的构造函数

    在 c 11 中 可以继承构造函数 我有以下代码 重现示例 但无法编译 template
  • 如何在console.log中打印JSON数据?

    我无法从 JavaScript 访问 JSON 数据 请帮助我如何在 javascript 中从 JSON 数据访问数据 我有一个 JSON 数据 例如 success true input data quantity row 122 1
  • 指定端口时Django runserver错误

    我最近习惯在 django 项目中执行以下操作 以便我可以在各种操作系统 即非 Linux 上测试 Bowser 兼容性 sudo manage py runserver 0 0 0 0 80 这使我可以通过网络上的任何计算机访问该项目 但
  • Django 跨站反向 URL

    可能是简单的问题 我只是错过了一些东西 但我没有想法 我有 Django 项目 为多个具有不同特性的站点提供服务sessions py并且完全不同ROOT URLCONFs 一个站点处理用户注册 身份验证和配置文件设置 其他站点 在另一个域
  • 使用 Shapeless 将嵌套案例类转换为嵌套映射

    我正在尝试使用 Shapeless 解决 this 1 问题 总而言之 它是将嵌套案例类转换为 Map String Any 以下是示例 case class Person name String address Address case