Работа с YAML для Scala
Я нашел одну библиотеку для этого https://github.com/daltontf/scala-yaml, но похоже, что не многие разработчики используют ее, и она довольно устарела. Это также может быть http://www.lag.net/configgy/, если ссылка не была мертвой.
Интересно, какая самая популярная или де-факто библиотека для работы с YAML в Scala?
Ответы
Ответ 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)