Shapeless code to convert Map[String, Any] to case class cannot handle optional substructures2019 Community Moderator ElectionConverting Map[String,Any] to a case class using ShapelessHow to use shapeless to convert generic Map[String, Any] to case class inside generic function?How to convert generic potentially nested Map[String, Any] to case class using any library in Scala?Case class to map in ScalaConvert Nested Case Classes to Nested Maps in ScalaConvert a List[String] to a case class using ShapelessConverting nested case classes to nested Maps using ShapelessConverting Map[String,Any] to a case class using ShapelessUnable to convert Scrooge generated classes to maps using ShapelessHow to use shapeless to copy fields from one class to another different classGetter on nested case classTrim values of String fields of a case classHow to use shapeless to convert generic Map[String, Any] to case class inside generic function?
Plywood subfloor won't screw down in a trailer home
Rejected in 4th interview round citing insufficient years of experience
How is the Swiss post e-voting system supposed to work, and how was it wrong?
How do anti-virus programs start at Windows boot?
Does splitting a potentially monolithic application into several smaller ones help prevent bugs?
Life insurance that covers only simultaneous/dual deaths
Time dilation for a moving electronic clock
What does おとこえしや mean?
Word for a person who has no opinion about whether god exists
"However" used in a conditional clause?
Is all copper pipe pretty much the same?
What is the dot in “1.2.4."
Replacing Windows 7 security updates with anti-virus?
Why does Deadpool say "You're welcome, Canada," after shooting Ryan Reynolds in the end credits?
Who is our nearest neighbor
Can the druid cantrip Thorn Whip really defeat a water weird this easily?
Does Linux have system calls to access all the features of the file systems it supports?
Can you reject a postdoc offer after the PI has paid a large sum for flights/accommodation for your visit?
Playing ONE triplet (not three)
How to make readers know that my work has used a hidden constraint?
Can "semicircle" be used to refer to a part-circle that is not a exact half-circle?
What has been your most complicated TikZ drawing?
My story is written in English, but is set in my home country. What language should I use for the dialogue?
When two POV characters meet
Shapeless code to convert Map[String, Any] to case class cannot handle optional substructures
2019 Community Moderator ElectionConverting Map[String,Any] to a case class using ShapelessHow to use shapeless to convert generic Map[String, Any] to case class inside generic function?How to convert generic potentially nested Map[String, Any] to case class using any library in Scala?Case class to map in ScalaConvert Nested Case Classes to Nested Maps in ScalaConvert a List[String] to a case class using ShapelessConverting nested case classes to nested Maps using ShapelessConverting Map[String,Any] to a case class using ShapelessUnable to convert Scrooge generated classes to maps using ShapelessHow to use shapeless to copy fields from one class to another different classGetter on nested case classTrim values of String fields of a case classHow to use shapeless to convert generic Map[String, Any] to case class inside generic function?
I'm trying to use this https://stackoverflow.com/a/31641779/1586965 (How to use shapeless to convert generic Map[String, Any] to case class inside generic function?) to process
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
I have a test that fails:
"Convert Map to PersonOptionalAddress Some" in
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
)) must_=== PersonOptionalAddress("Tom", Some(Address("Jefferson st", 10000)))
with
java.util.NoSuchElementException: None.get
If the substructure is not nested, or it is None, then the tests work fine.
I've also tried this, but it doesn't work either
"Convert Map to PersonOptionalAddress Some" in
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("x" -> Map("street" -> "Jefferson st", "zip" -> 10000))
)) must_=== PersonOptionalAddress("Tom", Some(Address("Jefferson st", 10000)))
scala generic-programming shapeless
add a comment |
I'm trying to use this https://stackoverflow.com/a/31641779/1586965 (How to use shapeless to convert generic Map[String, Any] to case class inside generic function?) to process
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
I have a test that fails:
"Convert Map to PersonOptionalAddress Some" in
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
)) must_=== PersonOptionalAddress("Tom", Some(Address("Jefferson st", 10000)))
with
java.util.NoSuchElementException: None.get
If the substructure is not nested, or it is None, then the tests work fine.
I've also tried this, but it doesn't work either
"Convert Map to PersonOptionalAddress Some" in
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("x" -> Map("street" -> "Jefferson st", "zip" -> 10000))
)) must_=== PersonOptionalAddress("Tom", Some(Address("Jefferson st", 10000)))
scala generic-programming shapeless
add a comment |
I'm trying to use this https://stackoverflow.com/a/31641779/1586965 (How to use shapeless to convert generic Map[String, Any] to case class inside generic function?) to process
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
I have a test that fails:
"Convert Map to PersonOptionalAddress Some" in
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
)) must_=== PersonOptionalAddress("Tom", Some(Address("Jefferson st", 10000)))
with
java.util.NoSuchElementException: None.get
If the substructure is not nested, or it is None, then the tests work fine.
I've also tried this, but it doesn't work either
"Convert Map to PersonOptionalAddress Some" in
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("x" -> Map("street" -> "Jefferson st", "zip" -> 10000))
)) must_=== PersonOptionalAddress("Tom", Some(Address("Jefferson st", 10000)))
scala generic-programming shapeless
I'm trying to use this https://stackoverflow.com/a/31641779/1586965 (How to use shapeless to convert generic Map[String, Any] to case class inside generic function?) to process
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
I have a test that fails:
"Convert Map to PersonOptionalAddress Some" in
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
)) must_=== PersonOptionalAddress("Tom", Some(Address("Jefferson st", 10000)))
with
java.util.NoSuchElementException: None.get
If the substructure is not nested, or it is None, then the tests work fine.
I've also tried this, but it doesn't work either
"Convert Map to PersonOptionalAddress Some" in
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("x" -> Map("street" -> "Jefferson st", "zip" -> 10000))
)) must_=== PersonOptionalAddress("Tom", Some(Address("Jefferson st", 10000)))
scala generic-programming shapeless
scala generic-programming shapeless
edited Mar 7 at 11:33
samthebest
asked Mar 7 at 11:02
samthebestsamthebest
19.7k1474112
19.7k1474112
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
If you want the code to work with PersonOptionalAddress
you should add one more instance of the type class so that it will work also with Map(
"name" -> "Tom",
"address" -> Some(Map ...)
)
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
The whole code
import shapeless._
import labelled.FieldType, field
object App {
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
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
trait CaseClassFromMap[P <: Product]
def apply(m: Map[String, Any]): Option[P]
object CaseClassFromMap
implicit def mk[P <: Product, R <: HList](implicit gen: LabelledGeneric.Aux[P, R],
fromMap: FromMap[R]): CaseClassFromMap[P] = new CaseClassFromMap[P]
def apply(m: Map[String, Any]): Option[P] = fromMap(m).map(gen.from)
def apply[P <: Product](map: Map[String, Any])(implicit fromMap: CaseClassFromMap[P]): P = fromMap(map).get
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
case class PersonAddress(name: String, address: Address)
def main(args: Array[String]): Unit =
println(
CaseClassFromMap[PersonAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonAddress(Tom,Address(Jefferson st,10000))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> None
))
)//PersonOptionalAddress(Tom,None)
hey thanks @Dmytro Mitin! I think we are nearly there, but it doesn't seem to work withNone
, i.e.Map("name" -> "Tom", "address" -> None)
– samthebest
Mar 8 at 15:46
See the update.hconsFromMap0opt
should be fixed.
– Dmytro Mitin
Mar 8 at 18:17
Thanks again @Dmytro Mitin, think I found another case where it doesn't seem to work. When we have a struct inside a list inside an option, e.g.case class Foo(foo: String); case class NestedFoo(foos: Option[List[Foo]])
thenMap[String, Any]("foos" -> Some(List(Map("foo" -> "value"))))
doesn't work
– samthebest
2 days ago
Surery it doesn't work for list. Why should it? You should define an instance for list if you want it to work for list.
– Dmytro Mitin
2 days ago
By the way, you incorrectly edited my answer. Now it states that " to work withPersonOptionalAddress
you should add one more instance ... so that it will work also withMap( ... "address" -> Some(Map ...)
". Actually making work withPersonOptionalAddress
vsPersonAddress
and withMap( ... "address" -> Some(Map ...)
vsMap( ... "address" -> Map ...
are different.
– Dmytro Mitin
2 days ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55042252%2fshapeless-code-to-convert-mapstring-any-to-case-class-cannot-handle-optional%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you want the code to work with PersonOptionalAddress
you should add one more instance of the type class so that it will work also with Map(
"name" -> "Tom",
"address" -> Some(Map ...)
)
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
The whole code
import shapeless._
import labelled.FieldType, field
object App {
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
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
trait CaseClassFromMap[P <: Product]
def apply(m: Map[String, Any]): Option[P]
object CaseClassFromMap
implicit def mk[P <: Product, R <: HList](implicit gen: LabelledGeneric.Aux[P, R],
fromMap: FromMap[R]): CaseClassFromMap[P] = new CaseClassFromMap[P]
def apply(m: Map[String, Any]): Option[P] = fromMap(m).map(gen.from)
def apply[P <: Product](map: Map[String, Any])(implicit fromMap: CaseClassFromMap[P]): P = fromMap(map).get
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
case class PersonAddress(name: String, address: Address)
def main(args: Array[String]): Unit =
println(
CaseClassFromMap[PersonAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonAddress(Tom,Address(Jefferson st,10000))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> None
))
)//PersonOptionalAddress(Tom,None)
hey thanks @Dmytro Mitin! I think we are nearly there, but it doesn't seem to work withNone
, i.e.Map("name" -> "Tom", "address" -> None)
– samthebest
Mar 8 at 15:46
See the update.hconsFromMap0opt
should be fixed.
– Dmytro Mitin
Mar 8 at 18:17
Thanks again @Dmytro Mitin, think I found another case where it doesn't seem to work. When we have a struct inside a list inside an option, e.g.case class Foo(foo: String); case class NestedFoo(foos: Option[List[Foo]])
thenMap[String, Any]("foos" -> Some(List(Map("foo" -> "value"))))
doesn't work
– samthebest
2 days ago
Surery it doesn't work for list. Why should it? You should define an instance for list if you want it to work for list.
– Dmytro Mitin
2 days ago
By the way, you incorrectly edited my answer. Now it states that " to work withPersonOptionalAddress
you should add one more instance ... so that it will work also withMap( ... "address" -> Some(Map ...)
". Actually making work withPersonOptionalAddress
vsPersonAddress
and withMap( ... "address" -> Some(Map ...)
vsMap( ... "address" -> Map ...
are different.
– Dmytro Mitin
2 days ago
add a comment |
If you want the code to work with PersonOptionalAddress
you should add one more instance of the type class so that it will work also with Map(
"name" -> "Tom",
"address" -> Some(Map ...)
)
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
The whole code
import shapeless._
import labelled.FieldType, field
object App {
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
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
trait CaseClassFromMap[P <: Product]
def apply(m: Map[String, Any]): Option[P]
object CaseClassFromMap
implicit def mk[P <: Product, R <: HList](implicit gen: LabelledGeneric.Aux[P, R],
fromMap: FromMap[R]): CaseClassFromMap[P] = new CaseClassFromMap[P]
def apply(m: Map[String, Any]): Option[P] = fromMap(m).map(gen.from)
def apply[P <: Product](map: Map[String, Any])(implicit fromMap: CaseClassFromMap[P]): P = fromMap(map).get
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
case class PersonAddress(name: String, address: Address)
def main(args: Array[String]): Unit =
println(
CaseClassFromMap[PersonAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonAddress(Tom,Address(Jefferson st,10000))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> None
))
)//PersonOptionalAddress(Tom,None)
hey thanks @Dmytro Mitin! I think we are nearly there, but it doesn't seem to work withNone
, i.e.Map("name" -> "Tom", "address" -> None)
– samthebest
Mar 8 at 15:46
See the update.hconsFromMap0opt
should be fixed.
– Dmytro Mitin
Mar 8 at 18:17
Thanks again @Dmytro Mitin, think I found another case where it doesn't seem to work. When we have a struct inside a list inside an option, e.g.case class Foo(foo: String); case class NestedFoo(foos: Option[List[Foo]])
thenMap[String, Any]("foos" -> Some(List(Map("foo" -> "value"))))
doesn't work
– samthebest
2 days ago
Surery it doesn't work for list. Why should it? You should define an instance for list if you want it to work for list.
– Dmytro Mitin
2 days ago
By the way, you incorrectly edited my answer. Now it states that " to work withPersonOptionalAddress
you should add one more instance ... so that it will work also withMap( ... "address" -> Some(Map ...)
". Actually making work withPersonOptionalAddress
vsPersonAddress
and withMap( ... "address" -> Some(Map ...)
vsMap( ... "address" -> Map ...
are different.
– Dmytro Mitin
2 days ago
add a comment |
If you want the code to work with PersonOptionalAddress
you should add one more instance of the type class so that it will work also with Map(
"name" -> "Tom",
"address" -> Some(Map ...)
)
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
The whole code
import shapeless._
import labelled.FieldType, field
object App {
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
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
trait CaseClassFromMap[P <: Product]
def apply(m: Map[String, Any]): Option[P]
object CaseClassFromMap
implicit def mk[P <: Product, R <: HList](implicit gen: LabelledGeneric.Aux[P, R],
fromMap: FromMap[R]): CaseClassFromMap[P] = new CaseClassFromMap[P]
def apply(m: Map[String, Any]): Option[P] = fromMap(m).map(gen.from)
def apply[P <: Product](map: Map[String, Any])(implicit fromMap: CaseClassFromMap[P]): P = fromMap(map).get
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
case class PersonAddress(name: String, address: Address)
def main(args: Array[String]): Unit =
println(
CaseClassFromMap[PersonAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonAddress(Tom,Address(Jefferson st,10000))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> None
))
)//PersonOptionalAddress(Tom,None)
If you want the code to work with PersonOptionalAddress
you should add one more instance of the type class so that it will work also with Map(
"name" -> "Tom",
"address" -> Some(Map ...)
)
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
The whole code
import shapeless._
import labelled.FieldType, field
object App {
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
implicit def hconsFromMap0opt[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, Option[V]] :: T] =
new FromMap[FieldType[K, Option[V]] :: T]
def apply(m: Map[String, Any]): Option[FieldType[K, Option[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](Some(gen.from(h))) :: t).orElse(for
v <- m.get(witness.value.name)
r1 <- Typeable[Option[Map[String, Any]]].cast(v)
opt = for
r <- r1
h <- fromMapH(r)
yield gen.from(h)
t <- fromMapT(m)
yield field[K](opt) :: t)
trait CaseClassFromMap[P <: Product]
def apply(m: Map[String, Any]): Option[P]
object CaseClassFromMap
implicit def mk[P <: Product, R <: HList](implicit gen: LabelledGeneric.Aux[P, R],
fromMap: FromMap[R]): CaseClassFromMap[P] = new CaseClassFromMap[P]
def apply(m: Map[String, Any]): Option[P] = fromMap(m).map(gen.from)
def apply[P <: Product](map: Map[String, Any])(implicit fromMap: CaseClassFromMap[P]): P = fromMap(map).get
case class Address(street: String, zip: Int)
case class PersonOptionalAddress(name: String, address: Option[Address])
case class PersonAddress(name: String, address: Address)
def main(args: Array[String]): Unit =
println(
CaseClassFromMap[PersonAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonAddress(Tom,Address(Jefferson st,10000))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Map("street" -> "Jefferson st", "zip" -> 10000)
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> Some(Map("street" -> "Jefferson st", "zip" -> 10000))
))
)//PersonOptionalAddress(Tom,Some(Address(Jefferson st,10000)))
println(
CaseClassFromMap[PersonOptionalAddress](Map(
"name" -> "Tom",
"address" -> None
))
)//PersonOptionalAddress(Tom,None)
edited 2 days ago
samthebest
19.7k1474112
19.7k1474112
answered Mar 8 at 15:03
Dmytro MitinDmytro Mitin
7,603619
7,603619
hey thanks @Dmytro Mitin! I think we are nearly there, but it doesn't seem to work withNone
, i.e.Map("name" -> "Tom", "address" -> None)
– samthebest
Mar 8 at 15:46
See the update.hconsFromMap0opt
should be fixed.
– Dmytro Mitin
Mar 8 at 18:17
Thanks again @Dmytro Mitin, think I found another case where it doesn't seem to work. When we have a struct inside a list inside an option, e.g.case class Foo(foo: String); case class NestedFoo(foos: Option[List[Foo]])
thenMap[String, Any]("foos" -> Some(List(Map("foo" -> "value"))))
doesn't work
– samthebest
2 days ago
Surery it doesn't work for list. Why should it? You should define an instance for list if you want it to work for list.
– Dmytro Mitin
2 days ago
By the way, you incorrectly edited my answer. Now it states that " to work withPersonOptionalAddress
you should add one more instance ... so that it will work also withMap( ... "address" -> Some(Map ...)
". Actually making work withPersonOptionalAddress
vsPersonAddress
and withMap( ... "address" -> Some(Map ...)
vsMap( ... "address" -> Map ...
are different.
– Dmytro Mitin
2 days ago
add a comment |
hey thanks @Dmytro Mitin! I think we are nearly there, but it doesn't seem to work withNone
, i.e.Map("name" -> "Tom", "address" -> None)
– samthebest
Mar 8 at 15:46
See the update.hconsFromMap0opt
should be fixed.
– Dmytro Mitin
Mar 8 at 18:17
Thanks again @Dmytro Mitin, think I found another case where it doesn't seem to work. When we have a struct inside a list inside an option, e.g.case class Foo(foo: String); case class NestedFoo(foos: Option[List[Foo]])
thenMap[String, Any]("foos" -> Some(List(Map("foo" -> "value"))))
doesn't work
– samthebest
2 days ago
Surery it doesn't work for list. Why should it? You should define an instance for list if you want it to work for list.
– Dmytro Mitin
2 days ago
By the way, you incorrectly edited my answer. Now it states that " to work withPersonOptionalAddress
you should add one more instance ... so that it will work also withMap( ... "address" -> Some(Map ...)
". Actually making work withPersonOptionalAddress
vsPersonAddress
and withMap( ... "address" -> Some(Map ...)
vsMap( ... "address" -> Map ...
are different.
– Dmytro Mitin
2 days ago
hey thanks @Dmytro Mitin! I think we are nearly there, but it doesn't seem to work with
None
, i.e. Map("name" -> "Tom", "address" -> None)
– samthebest
Mar 8 at 15:46
hey thanks @Dmytro Mitin! I think we are nearly there, but it doesn't seem to work with
None
, i.e. Map("name" -> "Tom", "address" -> None)
– samthebest
Mar 8 at 15:46
See the update.
hconsFromMap0opt
should be fixed.– Dmytro Mitin
Mar 8 at 18:17
See the update.
hconsFromMap0opt
should be fixed.– Dmytro Mitin
Mar 8 at 18:17
Thanks again @Dmytro Mitin, think I found another case where it doesn't seem to work. When we have a struct inside a list inside an option, e.g.
case class Foo(foo: String); case class NestedFoo(foos: Option[List[Foo]])
then Map[String, Any]("foos" -> Some(List(Map("foo" -> "value"))))
doesn't work– samthebest
2 days ago
Thanks again @Dmytro Mitin, think I found another case where it doesn't seem to work. When we have a struct inside a list inside an option, e.g.
case class Foo(foo: String); case class NestedFoo(foos: Option[List[Foo]])
then Map[String, Any]("foos" -> Some(List(Map("foo" -> "value"))))
doesn't work– samthebest
2 days ago
Surery it doesn't work for list. Why should it? You should define an instance for list if you want it to work for list.
– Dmytro Mitin
2 days ago
Surery it doesn't work for list. Why should it? You should define an instance for list if you want it to work for list.
– Dmytro Mitin
2 days ago
By the way, you incorrectly edited my answer. Now it states that " to work with
PersonOptionalAddress
you should add one more instance ... so that it will work also with Map( ... "address" -> Some(Map ...)
". Actually making work with PersonOptionalAddress
vs PersonAddress
and with Map( ... "address" -> Some(Map ...)
vs Map( ... "address" -> Map ...
are different.– Dmytro Mitin
2 days ago
By the way, you incorrectly edited my answer. Now it states that " to work with
PersonOptionalAddress
you should add one more instance ... so that it will work also with Map( ... "address" -> Some(Map ...)
". Actually making work with PersonOptionalAddress
vs PersonAddress
and with Map( ... "address" -> Some(Map ...)
vs Map( ... "address" -> Map ...
are different.– Dmytro Mitin
2 days ago
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55042252%2fshapeless-code-to-convert-mapstring-any-to-case-class-cannot-handle-optional%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown