Scala:在嵌套映射中查找值(从JSON解析)
我将JSON转换为非常复杂的嵌套映射。 我只需要这张地图中的一个值。这是“系统”领域。 在我的示例中,值是“DEV130PHYSTEST”。 有人能帮我用Scala在地图上找到这个值吗Scala:在嵌套映射中查找值(从JSON解析),json,scala,Json,Scala,我将JSON转换为非常复杂的嵌套映射。 我只需要这张地图中的一个值。这是“系统”领域。 在我的示例中,值是“DEV130PHYSTEST”。 有人能帮我用Scala在地图上找到这个值吗 Some(Map(type -> SUCCESS, msg -> Container D4SContRules successfully called., result -> Map(execution-results -> Map(results -> List(Map(key -
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"
}
}
}]
}
}
}
我不确定我是否理解您的问题,但如果我理解正确,您需要的是找到存储在
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])
}
但是请注意,现在您不能简单地将[Any]列表转换为更具体的内容,如果您确定知道所有元素的类型并且类型相同,请使用map
转换以下值:
findAllValuesForKeyDeep(jsonObj, "order").map(v => v.asInstanceOf[Double])
您是否在为scala使用json库?哪一个?@Michael,如果这个答案有帮助的话,把它标记为accpedhallo@SergGr……用方法为一个键返回所有值的方式重构代码会很困难吗?你能给我一个提示或解决办法吗?Thankx@Michael,请参阅我的更新以了解
findAllValuesForKeyDeep