我正在编写一个scala方法,该方法读取Yaml文件并返回Yaml文件内容的Map。我可以成功完成此操作,但是使用数据结构非常麻烦,这将在下面进行演示。
请注意,我可以并且已经在scala中使用jackson来获取yaml文件并将其构成为case类。效果很好,使用起来也不麻烦。在这个问题中,yaml是动态的,因此我们需要将其放入动态数据结构中,即Map或Map List
在Java中,解决问题没有问题。返回的数据结构易于使用。
Java示例:
public Map readMapYml(String fullFileName) {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try {
return mapper.readValue(new File(fullFileName), Map.class);
} catch (Exception e) {
throw new RuntimeException("JavaParser->writeYml:
Unable to write yaml file: " + e.getMessage());
}
}
我等效的scala代码。 (我还尝试了下面的代码的许多变体)
def readMapYml(fullFileName: String): Map[String,Any] = {
val mapper = new ObjectMapper(new YAMLFactory())
mapper.registerModule(DefaultScalaModule)
try {
mapper.readValue(new File(fullFileName), classOf[Map[String,Any]])
}
catch {
case e: Exception =>
throw new RuntimeException("Parser->readMapYml: Unable to read yaml
file to map. filename: " + fullFileName + " Message: " + e.getMessage)
}
}
所以这可行,我可以解析数据,但这确实很麻烦。
麻烦的例子:
result.get("groups").get.asInstanceOf[List[Map[String,Any]]](0).get("group").get.asInstanceOf[Map[String,Any]].get("colors").get.asInstanceOf[List[Map[String,Any]]](0).get("color").get
Btw互操作性很好,我可以用Java编写并从scala调用它。但是,在这种情况下,我们需要使我们的Scala代码正常工作
我的问题:我希望fastxml Jackson返回一个数据结构,该结构易于使用,类似于我通过Java获得的数据结构。我该怎么办?
答案 0 :(得分:0)
以下代码可以很好地导航从Jackson返回的kv地图。
/**
* Purpose is to parse through a generic kv map of data returned from Jackson.
* @param structure data return from Jackson or a sub-structure of data returned from
Jackson
* @param path A path to the data we want to return. A stack so order is leaf to
branch to branch .... to root
* @return the section requested. The first item added to your stack. In other words
the last item pop.
*/
def getStructure(结构:任何,路径:mutable.Stack [String]):任何= {
var retVal: Any = structure
if (path.nonEmpty) {
structure match {
case map: Map[String, Any] =>
retVal = map.get(path.pop())
case some: Some[Any] =>
retVal = some.get
case list: List[Any] =>
retVal = list(path.pop().toInt)
case None =>
throw new IllegalStateException("DataHelper->getStructure: Bad path keyword does not exist in section of path. remaining stack: " + path)
case _ =>
throw new IllegalStateException("DataHelper->getStructure: Structure type is unexpected. Type: " + structure.getClass.getName)
}
if (path.nonEmpty) {
retVal = getStructure(retVal, path)
}
}
retVal match {
case some: Some[Any] =>
retVal = some.get //If the last item is a some get the content of the some.
case _ =>
}
retVal
}
测试代码:
test("testMyDataHelper") {
val mapParser = new MapParser
val result = mapParser.readMapYml("test.yaml")
var path = mutable.Stack[String]()
path.push("name","0","groups")
println(DataHelper.getStructure(result, path))//Joe
path.push("name","1","groups")
println(DataHelper.getStructure(result, path))//Bill
path.push("part2","0","items","0","groups")
println(DataHelper.getStructure(result,path))//dash
path.push("part2","2","items","0","groups")
println(DataHelper.getStructure(result,path))//line
//Example of getting a subsection of yaml
path.push("items","0","groups")
val subsection = DataHelper.getStructure(result,path)
//use the subsection
path.push("part1","2")
println(DataHelper.getStructure(subsection,path))//green
path.push("part2","0")
println(DataHelper.getStructure(subsection,path))//dash
}
yaml文件
document: "0.0.1"
groups:
- version: "0.0.0"
type: "A"
name: "Joe"
agency: "skjenco"
number: 8
items:
- part1: "red"
part2: "dash"
- part1: "brown"
part2: "underline"
- part1: "green"
part2: "line"
- version: "0.0.1"
type: "B"
name: "Bill"
agency: "billco"
number: 3
items:
- part1: "orange"
part2: "line"
- part1: "pink"
part2: "dash"
- part1: "blue"
part2: "line"
答案 1 :(得分:0)
以下方法的困难之一是,它要求每次提取数据时都要定义数据类型,而数据占用的数据类型为Any-因此迫使我们为值定义数据类型。
mapper.readValue(new File(fullFileName), classOf[Map[String,Any]])
由于预期YAML文件是动态的,因此最好使用来自Jackson的更加发达的JsonNode数据类型,并利用以下方法:
val yaml = mapper.readValue(new File(fullFileName), classOf[Any])
val jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(yaml)
val jsonObj = mapper.readTree(jsonString)
生成的jsonObj的数据类型为JsonNode,它将具有动态模式并通过其内置方法满足数据转换/类型转换需求