在没有'案例类的情况下阅读Scala中的YAML'

时间:2017-02-22 16:18:20

标签: scala jackson yaml snakeyaml

我正在尝试从YAML读取Scala文件,我可以使用下面给出的代码读取该文件。我在这里看到的一个缺点是我必须创建case class以使用我正在使用的YAML文件进行映射。每当我更改YAML的内容时,我都需要更改case class。在Scala中是否有任何方法可以阅读YAML 而不需要 创建case class。 (我还使用Python来阅读YAML;我们没有将ClassYAML结构进行映射的约束...并且想要做类似的事情Scala

中的事情

注意:当我在YAML中添加新属性时,如果我的case class没有匹配的属性,我会UnrecognizedPropertyException

package yamlexamples

import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule

object YamlTest extends App{


  case class Prop(country: String, state: List[String])

  val mapper: ObjectMapper = new ObjectMapper(new YAMLFactory())

  mapper.registerModule(DefaultScalaModule)
  val fileStream = getClass.getResourceAsStream("/sample.yaml")
  val prop:Prop = mapper.readValue(fileStream, classOf[Prop])

  println(prop.country + ", " + prop.state)

}

sample.yaml(这适用于代码)

country: US
state: 
  - TX
  - VA

sample.yaml(抛出异常)

country: US
state: 
  - TX
  - VA
continent: North America

2 个答案:

答案 0 :(得分:2)

您可以解析Yaml文件并将其作为集合对象加载而不是大小写。但这是以在代码中丢失类型安全为代价的。以下代码使用load支持的Yaml函数。请注意,load还有overloaded methods来读取输入流/阅读器。

import scala.collection.JavaConverters._
val yaml = new Yaml()
val data = yaml.load(
      """
        |country: US
        |state:
        |  - TX
        |  - VA
        |continent: North America
      """.stripMargin).asInstanceOf[java.util.Map[String, Any]].asScala

现在数据是scala可变集合而不是案例类

data: scala.collection.mutable.Map[String,Any] = Map(country -> US, state -> [TX, VA], continent -> North America)

答案 1 :(得分:1)

您可以使用Jackson或SnakeYaml解析YAML文件。但是,Jackson不支持引用/锚,而SnakeYaml支持。因此,最好使用SnakeYaml解析YAML文件并使用Jackson库访问数据元素

import java.io.{File, FileInputStream, FileReader}
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper}
import org.yaml.snakeyaml.Yaml 

// Parsing the YAML file with SnakeYAML - since Jackson Parser does not support Anchors and references
val ios = new FileInputStream(new File(yamlFilePath))
val yaml = new Yaml()
val mapper = new ObjectMapper().registerModules(DefaultScalaModule)
val yamlObj = yaml.loadAs(ios, classOf[Any])
    
// Converting the YAML to Jackson YAML - since it has more flexibility
val jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(yamlObj) // Formats YAML to a pretty printed JSON string - easy to read
val jsonObj = mapper.readTree(jsonString)

最后,您将获得JsonNode对象,该对象使我们能够转换为其他数据类型。