Подтвердить что ты не робот

Работа с YAML для Scala

Я нашел одну библиотеку для этого https://github.com/daltontf/scala-yaml, но похоже, что не многие разработчики используют ее, и она довольно устарела. Это также может быть http://www.lag.net/configgy/, если ссылка не была мертвой.

Интересно, какая самая популярная или де-факто библиотека для работы с YAML в Scala?

4b9b3361

Ответ 1

SnakeYAML - это высококачественный, активно поддерживаемый парсер/рендер YAML для Java. Конечно, вы можете использовать его из Scala.

HelicalYAML предоставляет оболочку Scala для SnakeYAML, если вы действительно хотите это удобство, но я не могу подтвердить качество или долговечность проекта.

Мне бы очень хотелось увидеть библиотеку, которая могла бы анализировать JSON или YAML (или что-то другое - подключаемое) к общему AST, а затем создавать объекты Scala с использованием классов типов. Несколько JSON-библиотек работают так (и, конечно же, могут также отображать JSON для объектов с использованием тех же самых типов), но я не знаю такого средства для YAML.

Ответ 2

Здесь приведен пример использования привязки

Добавьте эти зависимости:

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

Здесь наш внешний класс (Preconditions - проверка типа Guava и вызывает исключение, если указанное поле не находится в 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
}

И вот внутренний объект:

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

Наконец, вот как это сделать:

 val reader = new FileReader("sample.yaml")
 val mapper = new ObjectMapper(new YAMLFactory())
 val config: Sample = mapper.readValue(reader, classOf[Sample])

Ответ 3

Немного поздно, но я думаю, что этот метод работает самым плавным образом. Этот метод имеет:

  • Автоматическое преобразование типов scala
  • Использовать классы классов
  • Не нужно использовать шаблонный код, например BeanProperty/JsonProperty.
  • Использует Jackson-YAML и Jackson- 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)

Ответ 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)
  }
}

Ответ 5

Сегодня я встретил moultingyaml.

MoultingYAML - это обертка Scala для SnakeYAML на основе спрей-json.

Мне это хорошо знакомо, много лет работая с spray-json. Я думаю, что это может поместиться @sihil в "убедительной" и "зрелой" библиотеке YAML Scala.

Ответ 6

Поэтому у меня недостаточно репутации, чтобы комментировать (41 atm), но я думал, что мой опыт заслуживает упоминания.

После прочтения этой темы я решил попробовать использовать парсер Jackson YAML, потому что мне не нужны конструкторы с нулевым аргументом, и это было гораздо более удобочитаемо. Я не понял, что нет поддержки для наследования (слияния), и существует ограниченная поддержка привязки (не это ли целая точка YAML?).

Объясняется здесь.

Ссылка на якорь объясняется здесь. Хотя оказывается, что поддерживается сложная ссылка на привязку, я не мог заставить ее работать в простом случае.

Ответ 7

По моему опыту библиотеки JSON для Scala более зрелые и более простые в использовании (ни один из подходов YAML не является чрезвычайно привлекательным или зрелым, как эквиваленты JSON, когда дело касается классов классов или написания пользовательских сериализаторов и десеризаторов).

Как таковой, я предпочитаю конвертировать из YAML в JSON, а затем использовать библиотеку JSON. это может показаться немного сумасшедшим, но оно работает очень хорошо при условии, что:

  • Вы работаете только с YAML, который является подмножеством JSON (много примеров использования в моем опыте).
  • Путь не критичен по производительности (поскольку при использовании этого подхода возникают накладные расходы)

Подход, который я использую для преобразования из YAML в JSON, использует Джексона:

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

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