在 Scala 中使用 YAML

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19441400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:46:07  来源:igfitidea点击:

Working with YAML for Scala

scalayaml

提问by アレックス

I found one library for this https://github.com/daltontf/scala-yaml, but it seems like not many developers use it and it's pretty outdated. It also might be this http://www.lag.net/configgy/if the link wasn't dead.

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

I wonder, what is the most popular or de-facto library for working with YAML in Scala?

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

采纳答案by AmigoNico

SnakeYAMLis a high-quality, actively maintained YAML parser/renderer for Java. You can of course use it from Scala.

SnakeYAML是一个高质量的、积极维护的 Java YAML 解析器/渲染器。您当然可以从 Scala 使用它。

HelicalYAMLprovides a Scala wrapper for SnakeYAML if you really want that convenience, but I can't attest to the quality or longevity of the project.

如果您真的想要这种便利,HelicalYAMLSnakeYAML提供了 Scala 包装器,但我无法证明该项目的质量或寿命。

I would love to see a library that could parse either JSON or YAML (or whatever -- pluggable) to a common AST and then construct Scala objects using typeclasses. Several JSON libraries work like that (and of course can also render JSON for objects using the same typeclasses), but I don't know of such a facility for YAML.

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

回答by Greg Kopff

Here's an example of using the Hymanson YAMLdatabinding.

这是使用Hymanson YAML数据绑定的示例。

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.Hymanson.core" % "Hymanson-core" % "2.1.1",
  "com.fasterxml.Hymanson.core" % "Hymanson-annotations" % "2.1.1",
  "com.fasterxml.Hymanson.core" % "Hymanson-databind" % "2.1.1",
  "com.fasterxml.Hymanson.dataformat" % "Hymanson-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):

这是我们最外面的类(前提条件是一个类似番石榴的检查,如果所述字段不在 YAML 中,则会引发异常):

import java.util.{List => JList, Map => JMap}
import collection.JavaConversions._
import com.fasterxml.Hymanson.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.Hymanson.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])

回答by Gaurav Kumar

A little late to the party but I think this method works in the most seamless way. This method has:

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

  1. Automatic conversion to scala collection types
  2. Use case classes
  3. No need for boilerplate code like BeanProperty/JsonProperty
  4. Uses Hymanson-YAML& Hymanson-scala
  1. 自动转换为 Scala 集合类型
  2. 用例类
  3. 不需要像 BeanProperty/JsonProperty 这样的样板代码
  4. 使用Hymanson-YAMLHymanson-scala

Code:

代码:

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

case class Prop(url: List[String])

// uses Hymanson 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)

回答by SemanticBeeng

And now we have circe-yamlhttps://github.com/circe/circe-yaml

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

SnakeYAML provides a Java API for parsing YAML and marshalling its structures into JVM classes. However, you might find circe's way of marshalling into a Scala ADT preferable -- using compile-time specification or derivation rather than runtime reflection. This enables you to parse YAML into Json, and use your existing (or circe's generic) Decoders to perform the ADT marshalling. You can also use circe's Encoder to obtain a Json, and print that to YAML using this library.

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

回答by akauppi

I came across moultingyamltoday.

我今天遇到了moultingyaml

MoultingYAML is a Scala wrapper for SnakeYAML based on spray-json.

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

It looks quite familiar to me, having worked years with spray-json. I think it might fit @sihil's need of a "compelling" and "mature" Scala YAML library.

我看起来很熟悉,与spray-json. 我认为它可能适合@sihil 对“引人注目”和“成熟”的 Scala YAML 库的需求。

回答by Peter Klipfel

For anyone else that runs across this answer and is looking for help and examples, I found a basic examplethat uses snakeYAML Hope it helps. Here's the code:

对于遇到此答案并正在寻找帮助和示例的其他任何人,我找到了一个使用 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)
  }
}

回答by Daniel Fithian

So I don't have enough reputation to comment (41 atm) but I thought my experience was worth mentioning.

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

After reading this thread, I decided to try to use the Hymanson YAML parser because I didn't want zero-argument constructors and it was much more readable. What I didn't realize was that there is no support for inheritance (merging), and there is limited support for anchor reference(isn't that the whole point of YAML??).

读完这篇文章后,我决定尝试使用 Hymanson YAML 解析器,因为我不想要零参数构造函数,而且它更具可读性。我没有意识到的是不支持继承(合并),并且对锚引用的支持有限(这不是 YAML 的全部内容吗??)。

Merge is explained here.

此处解释合并。

Anchor reference is explained here. While it appears that complex anchor reference is supported, I could not get it to work in a simple case.

锚引用在这里解释。虽然看起来支持复杂的锚引用,但我无法让它在简单的情况下工作。

回答by sihil

In my experience JSON libraries for Scala are more mature and easier to use (none of the YAML approaches are enormously compelling or as mature as JSON equivalents when it comes to dealing with case classes or writing custom serialisers and deserialisers).

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

As such I prefer to converting from YAML to JSON and then use a JSON library. this might sound slightly crazy but it works really well provided that:

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

  • You are only working with YAML that is a subset of JSON (a great deal of use cases in my experience)
  • The path is not performance critical (as there is overhead in taking this approach)
  • 您只使用作为 JSON 子集的 YAML(根据我的经验有很多用例)
  • 路径不是性能关键(因为采用这种方法会产生开销)

The approach I use for converting from YAML to JSON leverages Hymanson:

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

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

val json = new ObjectMapper()
        .writer(new DefaultPrettyPrinter().withoutSpacesInObjectEntries())
        .writeValueAsString(tree)