Скала быстрее xml Джексон.Чтение в файле Yaml, но с структурой возвращаемых данных трудно работать - PullRequest
0 голосов
/ 17 октября 2018

Я пишу метод scala, который читает файл Yaml и возвращает карту содержимого файла Yaml.Я могу сделать это успешно, но работа со структурой данных очень громоздка, как я покажу ниже.

Примечание. Я могу и использовал Джексона в Scala, чтобы взять файл yaml и превратить его в класс case.Это прекрасно работает и не громоздко в использовании.В этой проблеме 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-код работал

Мой вопрос: я хотел бы, чтобы Джексон fastxml возвращал структуру данных, которую намного проще использовать, аналогично структуре данных, которую я получаю, когда делаю через Java,Как мне это сделать?

1 Ответ

0 голосов
/ 19 октября 2018

Следующий код хорошо выполняет навигацию по карте 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"
...