当前位置: 首页 > 知识库问答 >
问题:

使用Shapeless将map[String,any]转换为case类

钱振
2023-03-14
val mp = Map("name" -> "Tom", "address" -> Map("street" -> "Jefferson st", "zip" -> 10000))
case class Person(name:String, address:Address)
case class Address(street:String, zip:Int)

val p = Person("Tom", Address("Jefferson st", 10000))
val newP = mp.asCC[Person]
assert(newP.get == p)

共有1个答案

柳俊彦
2023-03-14

这里有一个现成的,大部分未经测试的解决方案。首先是type类:

import shapeless._, labelled.{ FieldType, field }

trait FromMap[L <: HList] {
  def apply(m: Map[String, Any]): Option[L]
}

然后是实例:

trait LowPriorityFromMap {
  implicit def hconsFromMap1[K <: Symbol, V, T <: HList](implicit
    witness: Witness.Aux[K],
    typeable: Typeable[V],
    fromMapT: Lazy[FromMap[T]]
  ): FromMap[FieldType[K, V] :: T] = new FromMap[FieldType[K, V] :: T] {
    def apply(m: Map[String, Any]): Option[FieldType[K, V] :: T] = for {
      v <- m.get(witness.value.name)
      h <- typeable.cast(v)
      t <- fromMapT.value(m)
    } yield field[K](h) :: t
  }
}

object FromMap extends LowPriorityFromMap {
  implicit val hnilFromMap: FromMap[HNil] = new FromMap[HNil] {
    def apply(m: Map[String, Any]): Option[HNil] = Some(HNil)
  }

  implicit def hconsFromMap0[K <: Symbol, V, R <: HList, T <: HList](implicit
    witness: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, R],
    fromMapH: FromMap[R],
    fromMapT: FromMap[T]
  ): FromMap[FieldType[K, V] :: T] = new FromMap[FieldType[K, V] :: T] {
    def apply(m: Map[String, Any]): Option[FieldType[K, V] :: T] = for {
      v <- m.get(witness.value.name)
      r <- Typeable[Map[String, Any]].cast(v)
      h <- fromMapH(r)
      t <- fromMapT(m)
    } yield field[K](gen.from(h)) :: t
  }
}

然后为方便起见创建一个帮助器类:

class ConvertHelper[A] {
  def from[R <: HList](m: Map[String, Any])(implicit
    gen: LabelledGeneric.Aux[A, R],
    fromMap: FromMap[R]
  ): Option[A] = fromMap(m).map(gen.from(_))
}

def to[A]: ConvertHelper[A] = new ConvertHelper[A]

和示例:

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

val mp = Map(
  "name" -> "Tom",
  "address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
)
scala> to[Person].from(mp)
res0: Option[Person] = Some(Person(Tom,Address(Jefferson st,10000)))
 类似资料:
  • 问题内容: 如何将java.util.Map [String,Object]转换为scala.collection.immutable.Map [String,Any],以便将原始映射中的所有值(整数,布尔值等)都转换为正确的值,以在Scala中运作良好。 问题答案: 正如VonC所说,仅支持可变集合,但您不必使用单独的库。派生可变集合,从该集合定义了一个返回不可变Map的方法: 这将输出

  • 问题内容: 从来源来看,我无法影响我在地图中获得的数据,该地图以表示。 我需要处理所包含的数据,最好是(其中的数据非常适合该处理)。 我还需要从数据中生成键列表,因为这些键是事先未知的。 我可以在网上找到的大多数类似问题或多或少都说这是不可能的,但是如果我的地图是,则表明数据在那里,可读性为。 我该怎么办fmt.Println可以做什么? 问题答案: 处理未知接口的一种安全方法,只需使用fmt.S

  • 我有一个实体 我想根据货币计算每个部门的金额,并将结果写在行中。例子: 结果:“莫斯科200美元,巴黎100美元,莫斯科200卢布” 对于it: 我收到一个结果: 但我不知道如何转换地图

  • 我对反思并不是很高兴,这个答案使用无形状代码在某些情况下(但似乎有许多边缘情况)可以使用无形状代码将MAP[String,Any]转换为case类,不能处理可选的子结构

  • 我有个方法 所以本质上是这样的: exec(这里的一些java魔术将str3转换为string[],然后将这个string[]传递给这个exec方法本身);

  • 问题内容: 我正在开发一些应用程序,它允许从SD卡中选择图像,将其保存到数据库中并为ImageView设置此值。我需要知道将uri转换为字符串并将字符串转换为uri的方法。现在,我使用了Uri的getEncodedPath()方法,但是例如,此代码不起作用: 因此,我不知道如何将Uri保存到数据库中并根据保存的值创建新的Uri。请帮我修复它。 问题答案: 我需要知道将uri转换为字符串并将字符串转