2013-10-18 89 views

回答

21

SnakeYAML是一種高品質的,積極的維護YAML解析器/呈現爲Java。你當然可以在Scala中使用它。

HelicalYAML提供了斯卡拉包裝器SnakeYAML如果你真的想要的便利,但我不能證明該項目的質量和壽命。

我很想看到,可以解析JSON或YAML庫(或其他 - 可插拔),以一個共同的AST,然後構建使用類型類斯卡拉對象。幾個JSON庫像這樣工作(當然也可以使用相同的類型類來渲染JSON),但我不知道YAML有這樣的工具。

+0

HelicalYAML目前沒有維護(根據項目網站;最新的提交是在2010年) – fikovnik

+2

對我來說,使用SnakeYAML的主要缺點是,如果你想自動解析,你只能用java集合序列化可變類使用反射。這讓我寫了2個班。在代碼和beany中使用的不可變的一個,它具有@BeanProperties,並使用帶有構建方法的java集合來構建不可變的伴侶。我錯過了什麼?也許有一些基於宏的元編程解決方案可以讓我擺脫雙重編碼? –

4

對於運行此答案並尋找幫助和示例的其他人,我發現使用snakeYAML的basic example希望它有幫助。下面的代碼:

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

下面是一個使用Jackson YAML數據綁定的例子。

首先,這裏是我們的樣本文件:

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

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

添加這些依賴關係:

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

下面是我們最一流的(前提是番石榴般的檢查,如果所述的場不是拋出一個異常在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]) 
+0

傑克遜圖書館的使用情況。 –

+0

我已經使用'jackson-dataformat-yaml'來維護應用程序配置好幾個月了。發現它比SnakeYaml更好。 –

+0

謝謝你的例子!我會將番石榴前提條件更改爲: 'require(_colour!= null,「color can not be null」); val color = _colour' – r90t

2

所以我沒有足夠的信譽評論(41個大氣壓),但我想我的經驗是值得一提。

閱讀此線程後,我決定嘗試使用傑克遜YAML解析器,因爲我不想零參數的構造函數,它是更具可讀性。我沒有意識到的是,沒有支持繼承(合併),並且對錨定引用的支持有限(不是YAML的全部內容?)。

合併解釋爲here

錨參考進行說明here。雖然似乎支持複雜的錨定引用,但我無法在簡單的情況下使用它。

16

晚會有點晚,但我認爲這種方法以最無縫的方式工作。這種方法有:

  1. 自動轉換爲斯卡拉集合類型
  2. 用例類
  3. 無需像中的BeanProperty/JsonProperty
  4. 用途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) 
+1

3年有點晚了? –

+3

斯卡拉永恆! :-) –

+2

3年* *不*延遲*這個*主題 - 因爲它仍然不是一個完全解決的問題。我正在使用上面給出的庫,但仍然遇到了特定的問題。 – javadba

1

根據我的經驗,用於Scala的JSON庫更成熟並且更易於使用(當談到處理案例類或編寫自定義序列化程序和反序列化程序時,沒有任何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) 
+1

你覺得moultingyaml怎麼樣 - 看我的回答 – akauppi

4

我對面傳來moultingyaml今天。

MoultingYAML是基於spray-json的SnakeYAML的Scala包裝。

看起來我很熟悉,在spray-json工作了幾年。我認爲這可能符合@ sihil對「引人注目」和「成熟」Scala YAML庫的需求。

+0

Moultingyaml似乎支持一個*範圍非常有限的單個案例。我想要支持嵌套地圖和列表。 – javadba

+0

Moultingyaml與s​​pray.json具有相同的抽象級別,對於spray.json,可以執行大約20行的模式匹配來處理我想要的內容。 – akauppi