Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How instantiate case class from Map[String, String]

Lets say I have

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

and

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

What is most concise way to instantiate any case class(if all fields are in map), signature like this:

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

Probably shapeless can help acomplish this task, but I am almost unfamiliar with it. Thanks!

like image 940
Andrei Markhel Avatar asked Jun 08 '26 19:06

Andrei Markhel


2 Answers

Firstly you can transform Map[String, String] into Map[Symbol, Any] and then use type classes shapeless.ops.maps.FromMap (or extention method .toRecord) and 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)
like image 64
Dmytro Mitin Avatar answered Jun 10 '26 09:06

Dmytro Mitin


If not using Shapeless is an option for you, you could do it in a simple way without it. Here is a sample implementation where I use the Try Monad and a pattern matching to transform the Map into your case class:

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

Of course this is a bit verbose than the Shapeless version, but if you do not want to use a full library just for this simple use case, you could always do it using Scala library!

like image 44
joesan Avatar answered Jun 10 '26 09:06

joesan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!