32

我为此https://github.com/daltontf/scala-yaml找到了一个库,但似乎没有多少开发人员使用它,而且它已经过时了。如果链接没有失效,它也可能是这个http://www.lag.net/configgy/ 。

我想知道,在 Scala 中使用 YAML 最流行或事实上的库是什么?

4

8 回答 8

27

Here's an example of using the Jackson YAML databinding.

First, here's our sample document:

name: test
parameters:
  "VERSION": 0.0.1-SNAPSHOT

things:
  - colour: green 
    priority: 128
  - colour: red
    priority: 64

Add these dependencies:

libraryDependencies ++= Seq(
  "com.fasterxml.jackson.core" % "jackson-core" % "2.1.1",
  "com.fasterxml.jackson.core" % "jackson-annotations" % "2.1.1",
  "com.fasterxml.jackson.core" % "jackson-databind" % "2.1.1",
  "com.fasterxml.jackson.dataformat" % "jackson-dataformat-yaml" % "2.1.1"
)

Here's our outermost class (Preconditions is a Guava-like check and raises an exception if said field is not in the YAML):

import java.util.{List => JList, Map => JMap}
import collection.JavaConversions._
import com.fasterxml.jackson.annotation.JsonProperty

class Sample(@JsonProperty("name") _name: String,
             @JsonProperty("parameters") _parameters: JMap[String, String],
             @JsonProperty("things") _things: JList[Thing]) {
  val name = Preconditions.checkNotNull(_name, "name cannot be null")
  val parameters: Map[String, String] = Preconditions.checkNotNull(_parameters, "parameters cannot be null").toMap
  val things: List[Thing] = Preconditions.checkNotNull(_things, "things cannot be null").toList
}

And here's the inner object:

import com.fasterxml.jackson.annotation.JsonProperty

class Thing(@JsonProperty("colour") _colour: String,
            @JsonProperty("priority") _priority: Int {
  val colour = Preconditions.checkNotNull(_colour, "colour cannot be null")
  val priority = Preconditions.checkNotNull(_priority, "priority cannot be null")
}

Finally, here's how to instantiate it:

 val reader = new FileReader("sample.yaml")
 val mapper = new ObjectMapper(new YAMLFactory())
 val config: Sample = mapper.readValue(reader, classOf[Sample])
于 2014-03-17T08:21:45.507 回答
26

聚会有点晚了,但我认为这种方法以最无缝的方式起作用。该方法具有:

  1. 自动转换为 scala 集合类型
  2. 用例类
  3. 不需要像 BeanProperty/JsonProperty 这样的样板代码
  4. 使用Jackson-YAMLJackson-scala

代码:

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

case class Prop(url: List[String])

// uses Jackson YAML to parsing, relies on SnakeYAML for low level handling
val mapper: ObjectMapper = new ObjectMapper(new YAMLFactory())

// provides all of the Scala goodiness
mapper.registerModule(DefaultScalaModule)
val prop: Prop = mapper.readValue("url: [abc, def]", classOf[Prop])

// prints List(abc, def)
println(prop.url)
于 2016-04-24T09:19:20.837 回答
24

SnakeYAML是用于 Java 的高质量、积极维护的 YAML 解析器/渲染器。你当然可以在 Scala 中使用它。

如果您已经在使用circe,您可能对circe-yaml感兴趣,它使用SnakeYAML解析 YAML 文件,然后将结果转换为 circe AST。

我希望看到一个库可以将 JSON 或 YAML(或任何可插入的)解析为通用 AST,然后使用类型类构造 Scala 对象。几个 JSON 库就是这样工作的(当然也可以为使用相同类型类的对象呈现 JSON),但我不知道 YAML 有这样的工具。


PS: SnakeYAML 似乎还有一些看似废弃的包装器,即HelicalYAMLyaml4s

于 2013-10-19T01:01:55.033 回答
10

现在我们有了circe-yaml https://github.com/circe/circe-yaml

SnakeYAML 提供了一个用于解析 YAML 并将其结构编组为 JVM 类的 Java API。但是,您可能会发现 circe 编组为 Scala ADT 的方式更可取——使用编译时规范或派生而不是运行时反射。这使您能够将 YAML 解析为 Json,并使用您现有的(或 circe 的通用)解码器来执行 ADT 编组。您还可以使用 circe 的 Encoder 获取 Json,并使用此库将其打印到 YAML。

于 2018-04-18T10:23:34.517 回答
6

我今天遇到了moultingyaml

MoultingYAML 是基于 spray-json 的 SnakeYAML 的 Scala 包装器。

在我工作多年后,它看起来很熟悉spray-json。我认为它可能符合@sihil 对“引人注目”和“成熟”的 Scala YAML 库的需求。

于 2016-11-18T13:45:04.433 回答
4

对于遇到此答案并正在寻找帮助和示例的其他任何人,我找到了一个使用snakeYAML的基本示例,希望对您有所帮助。这是代码:

package yaml

import org.yaml.snakeyaml.Yaml
import org.yaml.snakeyaml.constructor.Constructor
import scala.collection.mutable.ListBuffer
import scala.reflect.BeanProperty

object YamlBeanTest1 {

  val text = """
  accountName: Ymail Account
  username: USERNAME
  password: PASSWORD
  mailbox: INBOX
  imapServerUrl: imap.mail.yahoo.com
  protocol: imaps
  minutesBetweenChecks: 1
  usersOfInterest: [barney, betty, wilma]
  """

  def main(args: Array[String]) {
    val yaml = new Yaml(new Constructor(classOf[EmailAccount]))
    val e = yaml.load(text).asInstanceOf[EmailAccount]
    println(e)
  }

}

/**
 * With the Snakeyaml Constructor approach shown in the main method,
 * this class must have a no-args constructor.
 */
class EmailAccount {
  @BeanProperty var accountName: String = null
  @BeanProperty var username: String = null
  @BeanProperty var password: String = null
  @BeanProperty var mailbox: String = null
  @BeanProperty var imapServerUrl: String = null
  @BeanProperty var minutesBetweenChecks: Int = 0
  @BeanProperty var protocol: String = null
  @BeanProperty var usersOfInterest = new java.util.ArrayList[String]()

  override def toString: String = {
    return format("acct (%s), user (%s), url (%s)", accountName, username, imapServerUrl)
  }
}
于 2014-03-12T23:45:33.130 回答
4

所以我没有足够的声誉来发表评论(41 atm),但我认为我的经历值得一提。

在阅读了这个帖子之后,我决定尝试使用 Jackson YAML 解析器,因为我不想要零参数构造函数,而且它更具可读性。我没有意识到的是不支持继承(合并),并且对锚引用的支持有限(这不是 YAML 的全部意义吗??)。

合并在这里解释。

此处解释了锚参考。虽然似乎支持复杂的锚引用,但我无法让它在简单的情况下工作。

于 2015-12-11T14:42:48.197 回答
2

根据我的经验,用于 Scala 的 JSON 库更成熟且更易于使用(在处理案例类或编写自定义序列化器和反序列化器时,没有一种 YAML 方法非常引人注目或像 JSON 等价物那样成熟)。

因此,我更喜欢从 YAML 转换为 JSON,然后使用 JSON 库。这听起来可能有点疯狂,但它确实很好用,前提是:

  • 您只使用作为 JSON 子集的 YAML(根据我的经验,有很多用例)
  • 路径不是性能关键(因为采用这种方法存在开销)

我用于从 YAML 转换为 JSON 的方法利用了 Jackson:

val tree = new ObjectMapper(new YAMLFactory()).readTree(yamlTemplate)

val json = new ObjectMapper()
        .writer(new DefaultPrettyPrinter().withoutSpacesInObjectEntries())
        .writeValueAsString(tree)
于 2016-09-13T18:43:38.607 回答