我有Map[String, Any]
,例如来自JSON反序列化器:
def map: Map[String, Any] = Map("hello" -> Map("world" -> "value"))
我希望获得嵌套密钥Option
的{{1}}:
"hello"."world"
但是这个解决方案不是类型安全的 - 它会发出警告'未经检查,因为它被擦除'并且在错误的值类型上会失败。
如何以安全的方式实现这一目标?如果嵌套对象是包含键val value = map.get("hello").flatMap {
case m: Map[String, String] => m.get("value")
case _ => None
}
assert(value == Some("value"))
或"world"
的有效/兼容类型的地图,则返回值?
编辑:这不是None
或Manifest[]
。我知道确切的Map类型在运行时是不可访问的,但是想要以某种方式更好地解决投射键(这是安全的btw吗?)并对值进行TypeTag[]
。
答案 0 :(得分:2)
对于这种情况
val value = map.get("hello").flatMap {
case m: Map[String @unchecked, _] => m.get("value")
case _ => None
}
是安全的:如果m
的密钥类型不是String
,get
将只返回None
!您可以做的另一件事是使用实际的JSON AST,因为您
Map[String, Any]
现在,您可以轻松定义您想要的内容而无需强制转换,甚至可能不安全:
sealed trait JValue
...
case class JMap(underlying: Map[String, JValue]) {
def get(key: String) = underlying.get(key)
}
答案 1 :(得分:1)
仅仅是出于理论原因。可以这样做:
val value = map.get("hello").map {
case m: Map[_, _] => m collectFirst {case ("world", v) => v}
case _ => None
}
但它过于复杂,而且不实用。更糟糕的是,当在O(1)中搜索地图时,它会搜索O(n)中的内部Map
。
我认为你不能以任何其他方式做到这一点,我也不会推荐这个。虽然解决方案可能使用相同的想法,但更简单 - 不幸的是我想不出任何
答案 2 :(得分:0)
有一种优雅的方法可以解决这个问题。
1)声明TypeCase
import shapeless._
val mapType: TypeCase[Map[String, String]] = TypeCase[Map[String, String]]
2)在模式匹配上使用它以避免类型擦除
val value = Map("hello" -> Map("world" -> "value")).get("hello").flatMap {
case mapType(m) => m.get("world")
case _ => None
}
assert(value == Some("value"))
答案 3 :(得分:-1)
试试这个:
google.maps.event.addDomListener( window, 'load', function()