Scala fasterxml jackson.读取 Yaml 文件,但返回数据结构难以使用



>我正在编写一个scala方法,该方法读取Yaml文件并返回Yaml文件内容的映射。 我可以成功地做到这一点,但是使用数据结构非常麻烦,我将在下面演示。

注意我可以并且已经在scala中使用杰克逊来获取yaml文件并将其构成案例类。 这很好用,使用起来并不麻烦。 在这个问题中,yaml 是动态的,所以我们需要把它放入一个动态的数据结构中,即 Map 或 List of Map

在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

顺便说一句,互操作工作得很好,我可以用Java编写它并从scala调用它。 但是,在这种情况下,我们需要让我们的 scala 代码工作

我的问题:我希望更快的xml杰克逊返回一个数据结构,它更容易使用,类似于我通过Java返回的数据结构。 我该怎么做?

以下方法的困难之一是,每次我们提取数据时,它都需要定义数据类型,它占用数据类型 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数据类型,它将具有动态模式,并通过其内置方法支持数据转换/类型转换需求。

下面的代码很好地导航了从杰克逊返回的 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(structure: Any, path: mutable.堆栈[字符串](:任意 = {

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

}

亚姆尔文件

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"

最新更新