我将JSON转换为非常复杂的嵌套映射。 我只需要这张地图中的一个值。它是领域“系统”。 在我的示例中,值为“DEV130PHYSTEST”。 任何人都可以帮我在这张地图中用Scala找到这个值吗?
Some(Map(type -> SUCCESS, msg -> Container D4SContRules successfully called., result -> Map(execution-results -> Map(results -> List(Map(key -> , value -> 1.0), Map(key -> output, value -> List(Map(demo.d4srules.inputObj -> Map(order -> 1.0)), Map(demo.d4srules.outputObj -> Map(system -> DEV130PHYSTEST)))), Map(key -> input, value -> Map(demo.d4srules.inputObj -> Map(order -> 1.0)))), facts -> List(Map(key -> input, value -> Map(org.drools.core.common.DefaultFactHandle -> Map(external-form -> 0:1:1400441403:1400441403:1:DEFAULT:NON_TRAIT:demo.d4srules.inputObj))))))))
作为替代方案,我们也可以从JSON开始:
{
"type": "SUCCESS",
"msg": "Container D4SContRules successfully called.",
"result": {
"execution-results": {
"results": [{
"key": "",
"value": 1
},
{
"key": "output",
"value": [{
"demo.d4srules.inputObj": {
"order": 1
}
},
{
"demo.d4srules.outputObj": {
"system": "DEV130PHYSTEST"
}
}
]
},
{
"key": "input",
"value": {
"demo.d4srules.inputObj": {
"order": 1
}
}
}
],
"facts": [{
"key": "input",
"value": {
"org.drools.core.common.DefaultFactHandle": {
"external-form": "0:1:1640380:1640380:1:DEFAULT:NON_TRAIT:demo.d4srules.inputObj"
}
}
}]
}
}
}
答案 0 :(得分:0)
我不确定我理解你的问题,但是如果我理解正确的话,你想要的是找到存储在Map
中的一个键的值的某种方法,这个键可能在一些复杂的内部深处分层数据结构,你不知道或不想硬编码它的路径。如果是这种情况,您可以尝试这样的事情:
def findValueForKeyDeep[Key](container: Any, key: Key): Option[Any] = {
@tailrec
def findValueForKeyInTraversable(tr: Traversable[_], key: Key): Option[Any] = {
if (tr.isEmpty) None
else {
val headRes = findValueForKeyDeep(tr.head, key)
if (headRes.isDefined) headRes else findValueForKeyInTraversable(tr.tail, key)
}
}
container match {
case m: scala.collection.Map[Key, _] => m.get(key).orElse(findValueForKeyInTraversable(m.values, key))
case o: Option[_] => o.flatMap(findValueForKeyDeep(_, key))
case tr: Traversable[_] => findValueForKeyInTraversable(tr, key)
case _ => None
}
}
示例:
val jsonObj = Some(Map(
"type" -> "SUCCESS",
"msg" -> "Container D4SContRules successfully called.",
"result" ->
Map(
"execution-results" ->
Map(
"results" -> List(
Map(
"key" -> "",
"value" -> 1.0),
Map(
"key" -> "output",
"value" -> List(
Map("demo.d4srules.inputObj" -> Map("order" -> 1.0)),
Map("demo.d4srules.outputObj" -> Map("system" -> "DEV130PHYSTEST")))),
Map(
"key" -> "input",
"value" -> Map("demo.d4srules.inputObj" -> Map("order" -> 1.0)))),
"facts" -> List(
Map("key" -> "input",
"value" -> Map("org.drools.core.common.DefaultFactHandle" -> Map("external-form" -> "0:1:1400441403:1400441403:1:DEFAULT:NON_TRAIT:demo.d4srules.inputObj"))))))))
println(findValueForKeyDeep(jsonObj, "system"))
println(findValueForKeyDeep(jsonObj, "external-form"))
println(findValueForKeyDeep(jsonObj, "value"))
println(findValueForKeyDeep(jsonObj, "order"))
println(findValueForKeyDeep(jsonObj, "bad key"))
部分(DEV130PHYSTEST)
一些(0:1:1400441403:1400441403:1:DEFAULT:NON_TRAIT:demo.d4srules.inputObj)
一些(1.0)
一些(1.0)
没有
请注意,如果有多个匹配的键,则此代码返回其中一些键的值(任意)。另请注意,返回类型为Option[Any]
但如果您确定实际类型,则可以在调用后使用asInstanceOf
强制转换为该类型。
更新(找到所有匹配的值)
如果您想获得所有值,可以轻松完成
def findAllValuesForKeyDeep[Key](container: Any, key: Key): List[Any] = {
@tailrec
def findAllValuesForKeyDeepImpl(container: Any, key: Key, acc: List[Any]): List[Any] = {
container match {
case m: scala.collection.Map[Key, _] => {
val valueOption = m.get(key)
if (valueOption.isDefined)
valueOption.get :: acc
else
findAllValuesForKeyDeepImpl(m.values, key, acc)
}
case Some(v) => findAllValuesForKeyDeepImpl(v, key, acc)
case tr: Traversable[_] => findAllValuesForKeyInTraversable(tr, key, acc)
case _ => acc
}
}
@tailrec
def findAllValuesForKeyInTraversable(tr: Traversable[_], key: Key, acc: List[Any]): List[Any] = {
if (tr.isEmpty) acc
else {
val headAcc = findAllValuesForKeyDeepImpl(tr.head, key, acc)
findAllValuesForKeyInTraversable(tr.tail, key, headAcc)
}
}
findAllValuesForKeyDeepImpl(container, key, List.empty[Any])
}
但请注意,现在您不能简单地将List[Any]
转换为更具体的内容,如果您确定知道所有元素的类型且它们是相同的,请使用map
转换值比如
findAllValuesForKeyDeep(jsonObj, "order").map(v => v.asInstanceOf[Double])