如何从Map [String,String]实例化案例类

时间:2017-12-09 00:07:46

标签: scala shapeless

让我说我有

case class Sample(i:Int, b:Boolean) 

Map[String, String]("i" => "1", "b" => "false")

实例化任何案例类的最简洁方法是什么(如果所有字段都在地图中),签名如下:

 get[T](map:[String, String]) : T

可能没有形状可以帮助完成这项任务,但我几乎不熟悉它。谢谢!

3 个答案:

答案 0 :(得分:3)

首先,您可以将Map[String, String]转换为Map[Symbol, Any],然后使用类型类shapeless.ops.maps.FromMap(或扩展方法.toRecord)和LabelledGeneric

import shapeless.LabelledGeneric
import shapeless.record.Record
import shapeless.syntax.std.maps._

case class Sample(i: Int, b: Boolean)
val rec = Map('i -> 1, 'b -> false).toRecord[Record.`'i -> Int, 'b -> Boolean`.T].get
LabelledGeneric[Sample].from(rec) //Sample(1,false)

答案 1 :(得分:1)

如果不使用Shapeless是您的选择,您可以在没有它的情况下以简单的方式完成。下面是一个示例实现,我使用Try Monad和模式匹配将Map转换为您的案例类:

  (Try("1".toInt), Try("false".toBoolean)) match {
    case (Success(intVal), Success(boolVal)) =>
      Sample(intVal, boolVal)
    case _ => // Log and ignore the values
  }

当然这比Shapeless版本有点冗长,但如果您不想仅仅为这个简单的用例使用完整的库,那么您总是可以使用Scala库来完成它!

答案 2 :(得分:0)

人。可能我不太简洁。我真正需要的是从字符串映射到案例类的通用解析器。感谢您指出LabelledGeneric。这是解决方案:

{literal}
    <script>
      var dataLayer = window.dataLayer || [];
      dataLayer.push({
        'event' : 'productData',
        'name': 'productName',
        'id': 'productId',
        'price' : 123
      });
    </script>
{/literal}