Travailler avec YAML pour Scala

j'ai trouvé une bibliothèque pour ce https://github.com/daltontf/scala-yaml, mais il semble que pas beaucoup de des développeurs de l'utiliser et c'est assez obsolète. Il se peut aussi que ce soit cela http://www.lag.net/configgy/ si le lien n'était pas mort.

je me demande, Quelle est la bibliothèque la plus populaire ou de facto pour travailler avec YAML à Scala?

26
demandé sur アレックス 2013-10-18 08:06:21

8 réponses

SnakeYAML est un analyseur/rendereur YAML de haute qualité, activement entretenu pour Java. Vous pouvez bien sûr l'utiliser depuis Scala.

HelicalYAML fournit un emballage Scala pour SnakeYAML si vous voulez vraiment cette commodité, mais je ne peux pas attester de la qualité ou de la longévité du projet.

j'aimerais voir une bibliothèque qui pourrait analyser soit JSON ou YAML (ou n'importe quoi -- pluggable) à un AST commun et ensuite construire des objets Scala en utilisant typeclasses. Plusieurs bibliothèques JSON fonctionnent de cette façon (et bien sûr peuvent aussi rendre JSON pour des objets utilisant les mêmes classes typeclasses), mais je ne sais pas si une telle possibilité existe pour YAML.

21
répondu AmigoNico 2016-12-16 14:49:30

Voici un exemple d'utilisation de l' Jackson YAML liaison de données.

tout d'Abord, voici notre exemple de document:

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

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

Ajouter ces dépendances:

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"
)

voici notre classe la plus à l'extérieur (les conditions préalables sont un contrôle de type Guava et soulève une exception si ledit champ n'est pas dans le 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
}

et voici l'objet intérieur:

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")
}

Enfin, voici comment instancier:

 val reader = new FileReader("sample.yaml")
 val mapper = new ObjectMapper(new YAMLFactory())
 val config: Sample = mapper.readValue(reader, classOf[Sample])
22
répondu Greg Kopff 2014-03-17 08:26:54

Un peu en retard à la fête, mais je pense que cette méthode fonctionne dans la plus transparente. Cette méthode a:

  1. conversion automatique aux types de collecte scala
  2. utilisez les classes de cas
  3. Pas besoin de code réutilisable comme BeanProperty/JsonProperty
  4. Jackson-YAML& Jackson-scala

Code:

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)
18
répondu Gaurav Kumar 2016-04-24 09:26:02

je suis tombé sur moultingyaml aujourd'hui.

MoultingYAML est un emballage Scala pour SnakeYAML basé sur spray-json.

il me semble assez familier, ayant travaillé des années avec spray-json. Je pense que cela pourrait correspondre au besoin de @sihil d'une bibliothèque "convaincante" et "mature" Scala YAML.

5
répondu akauppi 2016-11-18 13:45:04

pour toute autre personne qui va à travers cette réponse et est à la recherche d'AIDE et d'exemples, j'ai trouvé un exemple de base qui utilise snakeYAML espère qu'il aide. Voici le code:

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)
  }
}
4
répondu Peter Klipfel 2014-03-12 23:45:33

donc je n'ai pas assez de réputation pour commenter (41 atm) mais j'ai pensé que mon expérience valait la peine d'être mentionnée.

après avoir lu ce thread, j'ai décidé d'essayer D'utiliser L'analyseur Jackson YAML parce que je ne voulais pas de constructeurs à argument zéro et que c'était beaucoup plus lisible. Ce que je n'avais pas réalisé c'était que il n'y a pas de support pour l'héritage (la fusion), et il y a un support limité pour l'ancre de référence (n'est-ce pas tout L'intérêt de YAML??).

la fusion est expliqué ici.

Ancre de référence est expliqué ici. Bien qu'il semble que la référence d'ancrage complexe soit supportée, Je n'ai pas pu la faire fonctionner dans un cas simple.

3
répondu Daniel Fithian 2015-12-11 14:42:48

d'après mon expérience, les bibliothèques JSON pour Scala sont plus mûres et plus faciles à utiliser (aucune des approches YAML n'est extrêmement convaincante ou aussi mûre que les équivalents JSON lorsqu'il s'agit de traiter des classes de cas ou d'écrire des sérialiseurs et des deserialiseurs personnalisés).

en tant que tel, je préfère passer de YAML à JSON et ensuite utiliser une bibliothèque JSON. cela peut sembler un peu fou mais cela fonctionne vraiment bien pourvu que:

  • vous ne travaillez QU'avec YAML qui est un sous-ensemble de JSON (un grand nombre de cas d'utilisation dans mon expérience)
  • Le chemin d'accès n'est pas critique pour les performances (comme il existe une surcharge dans la prise de cette approche)

L'approche que j'ai utiliser pour la conversion de DONNÉES en JSON exploite Jackson:

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

val json = new ObjectMapper()
        .writer(new DefaultPrettyPrinter().withoutSpacesInObjectEntries())
        .writeValueAsString(tree)
2
répondu sihil 2016-09-13 18:43:38

Et maintenant, nous avons circe-yamlhttps://github.com/circe/circe-yaml

SnakeYAML fournit une API Java pour analyser YAML et regrouper ses structures en classes JVM. Cependant, vous trouverez peut-être préférable que circe forme un Scala ADT, en utilisant la spécification ou la dérivation de la compilation plutôt que la réflexion de l'exécution. Cela vous permet D'analyser YAML en Json, et d'utiliser vos Décodeurs existants (ou génériques circe) pour effectuer L'ADT la sérialisation. Vous pouvez également utiliser l'encodeur de circe pour obtenir un Json, et l'imprimer à YAML en utilisant cette bibliothèque.

2
répondu SemanticBeeng 2018-04-18 10:23:34