Created
October 31, 2015 23:42
-
-
Save wolfendale/de5e3399f6bc80d009e2 to your computer and use it in GitHub Desktop.
Map[String, String] to Case Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package wolfendale | |
import shapeless._ | |
import shapeless.labelled._ | |
import scala.util.{Failure, Success, Try} | |
trait FromStringMap[A] { | |
def apply(data: Map[String, String]): Try[A] | |
} | |
object FromStringMap { | |
def apply[A0](implicit from: FromStringMap[A0]): FromStringMap[A0] = from | |
implicit def fromHnil: FromStringMap[HNil] = new FromStringMap[HNil] { | |
override def apply(data: Map[String, String]): Try[HNil] = Success(HNil) | |
} | |
implicit def fromHcons[H, T <: HList] | |
(implicit | |
fromHead: FromStringMap[H], | |
fromTail: FromStringMap[T] | |
): FromStringMap[H :: T] = new FromStringMap[H :: T] { | |
override def apply(data: Map[String, String]): Try[H :: T] = | |
for { | |
head <- fromHead(data) | |
tail <- fromTail(data) | |
} yield head :: tail | |
} | |
implicit def fromField[K <: Symbol, V] | |
(implicit | |
witnessK: Witness.Aux[K], | |
readsV: Reads[V] | |
): FromStringMap[FieldType[K, V]] = new FromStringMap[FieldType[K, V]] { | |
override def apply(data: Map[String, String]): Try[FieldType[K, V]] = | |
data.get(witnessK.value.name).fold[Try[FieldType[K, V]]](Failure(new Exception())) { | |
(str) => readsV(str) map { field[K](_) } | |
} | |
} | |
implicit def fromOptionField[K <: Symbol, V] | |
(implicit | |
witnessK: Witness.Aux[K], | |
readsV: Reads[V] | |
): FromStringMap[FieldType[K, Option[V]]] = new FromStringMap[FieldType[K, Option[V]]] { | |
override def apply(data: Map[String, String]): Try[FieldType[K, Option[V]]] = | |
data.get(witnessK.value.name).fold[Try[FieldType[K, Option[V]]]](Success(field[K](None))) { | |
(str) => readsV(str) map { x => field[K](Some(x)) } | |
} | |
} | |
implicit def fromGen[G, Repr <: HList] | |
(implicit | |
lgen: LabelledGeneric.Aux[G, Repr], | |
fromG: FromStringMap[Repr] | |
): FromStringMap[G] = new FromStringMap[G] { | |
override def apply(data: Map[String, String]): Try[G] = | |
fromG(data) map { lgen.from(_) } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package wolfendale | |
object FromStringMapApp extends App { | |
case class Foo(a: String, b: Int, c: Option[String]) | |
val from = FromStringMap[Foo] | |
println(from(Map("a" -> "foo", "b" -> "123", "c" -> "bar"))) | |
println(from(Map("a" -> "foo", "b" -> "123"))) | |
println(from(Map("a" -> "bar", "b" -> "foo", "c" -> "womble"))) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package wolfendale | |
import scala.util.{Success, Try} | |
trait Reads[A] { | |
def apply(str: String): Try[A] | |
} | |
object Reads { | |
implicit def readsString: Reads[String] = new Reads[String] { | |
override def apply(str: String): Try[String] = Success(str) | |
} | |
implicit def readsInt: Reads[Int] = new Reads[Int] { | |
override def apply(str: String): Try[Int] = Try { str.toInt } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment