2016-11-24 29 views
1

MoultingYaml從JSON轉換YAML到/是spray.json相象爲YAML,因此有着極大的好處。 > JSON -使用MoultingYaml

但是,它不適合轉換YAML <提供現成的支持。我認爲這樣做會很有用,至少作爲一個示例代碼使用例如spray.json認爲該項目與之密切相關。

如果有人提示/指針,以使這種simplish代碼,謝謝。如果沒有,我可能會在這裏發佈並在這裏發佈。

回答

0

您可以將YAML/JSON轉換爲中間的scala對象格式。類似的東西:

scala> import net.jcazevedo.moultingyaml.DefaultYamlProtocol._                            
import net.jcazevedo.moultingyaml.DefaultYamlProtocol._                              

scala> import net.jcazevedo.moultingyaml._                                 
import net.jcazevedo.moultingyaml._                                   

scala> import spray.json.DefaultJsonProtocol._                                
import spray.json.DefaultJsonProtocol._                                  

scala> import spray.json._                                     
import spray.json._                                      

scala> val jsonStr = "[1,2,3]"                                    
jsonStr: String = [1,2,3]                                     

scala> val jsonAst = jsonStr.parseJson                                  
jsonAst: spray.json.JsValue = [1,2,3]                                  

scala> val yamlAst = jsonAst.convertTo[List[Int]](spray.json.DefaultJsonProtocol.listFormat).toYaml(net.jcazevedo.moultingyaml.DefaultYamlProtocol.listFormat)    
yamlAst: net.jcazevedo.moultingyaml.YamlValue = YamlArray(Vector(YamlNumber(1), YamlNumber(2), YamlNumber(3)))                

scala> val yamlStr = yamlAst.prettyPrint                                 
yamlStr: String =                                       
"- 1                                          
- 2                                           
- 3                                           
"                                           

scala> val recoveredJsonAst = yamlAst.convertTo[List[Int]](net.jcazevedo.moultingyaml.DefaultYamlProtocol.listFormat).toJson(spray.json.DefaultJsonProtocol.listFormat)  
recoveredJsonAst: spray.json.JsValue = [1,2,3]                                

scala> val recoveredJsonStr = recoveredJsonAst.prettyPrint                             
recoveredJsonStr: String = [1, 2, 3]       

這裏YAML AST被轉換成域對象List[Int]然後JSON AST,反之亦然。你可以在AST之間做直接轉換,但是你必須自己寫 - 更多的工作,但更好的性能。

這是很好的YAML庫模仿熟悉的JSON庫接口,但應對implicits變得更加複雜。此外,像convertTo這樣的方法很難解決,因爲這一點。像listFormat進口變得模糊等

當有稍微乾淨少衝突:

scala> case class Test(v: Int)                           
defined class Test                              


scala> import net.jcazevedo.moultingyaml.DefaultYamlProtocol._                   
import net.jcazevedo.moultingyaml.DefaultYamlProtocol._                     

scala> import net.jcazevedo.moultingyaml._                        
import net.jcazevedo.moultingyaml._                          

scala> import spray.json.DefaultJsonProtocol._                       
import spray.json.DefaultJsonProtocol._                         

scala> import spray.json._                            
import spray.json._                              


scala> implicit val TestAsJson = jsonFormat1(Test)                      
TestAsJson: spray.json.RootJsonFormat[Test] = [email protected]          

scala> implicit val TestAsYaml = yamlFormat1(Test)                      
TestAsYaml: net.jcazevedo.moultingyaml.YamlFormat[Test] = [email protected]     

scala> val jsonStr = """{"v":1}"""                          
jsonStr: String = {"v":1}                            

scala> val jsonAst = jsonStr.parseJson                         
jsonAst: spray.json.JsValue = {"v":1}                         

scala> val yamlAst = jsonAst.convertTo[Test].toYaml                      
yamlAst: net.jcazevedo.moultingyaml.YamlValue = YamlObject(Map(YamlString(v) -> YamlNumber(1)))           

scala> val yamlStr = yamlAst.prettyPrint                         
yamlStr: String =                              
"v: 1                                 
"                                  

scala> val recoveredJsonAst = yamlAst.convertTo[Test].toJson                    
recoveredJsonAst: spray.json.JsValue = {"v":1}                       

scala> val recoveredJsonStr = recoveredJsonAst.prettyPrint                    
recoveredJsonStr: String =                            
{                                  
    "v": 1                                 
}   
+0

謝謝@aleksey我有一個直接的AST到AST解決方案烹飪。一旦我得到測試並且通過,它會在這裏發佈。我需要支持「任何」JSON數據。 – akauppi

0

這是我想出了。

import spray.json._ 
import net.jcazevedo.{moultingyaml => my} 
import net.jcazevedo.moultingyaml._ 
import net.jcazevedo.moultingyaml.DefaultYamlProtocol._ 

object JsonYamlProtocol extends my.CollectionFormats { 

    implicit object JsValueYamlFormat extends YamlFormat[JsValue] { 

    override 
    def write(jv: JsValue) = jv match { 
     case JsNumber(n) => YamlNumber(n) 
     case JsString(s) => YamlString(s) 
     case a: JsArray => seqFormat[JsValue].write(a.elements) 
     case o: JsObject => mapFormat[String,JsValue].write(o.fields) 
     case JsBoolean(b) => YamlBoolean(b) 
     case JsNull => YamlNull 
     case x => my.serializationError(s"Unexpected JSON value: $x") 
    } 

    override 
    def read(yv: YamlValue): JsValue = yv match { 
     // tbd. probably can be simplified 
     case x: YamlNumber[_] => x.value match { 
     //case xx: Int => JsNumber(xx) 
     //case xx: Double => JsNumber(xx) 
     case xx: BigDecimal => JsNumber(xx) 
     } 
     case YamlString(s) => JsString(s) 
     case a: YamlArray => JsArray(vectorFormat[JsValue].read(a)) 
     case o: YamlObject => JsObject(mapFormat[String, JsValue].read(o)) 
     case YamlBoolean(b) => JsBoolean(b) 
     case YamlNull => JsNull 
     case x => my.deserializationError(s"Unexpected YAML value: $x") 
    } 
    } 

    implicit object JsObjectYamlFormat extends YamlFormat[JsObject] { 

    override 
    def write(jso: JsObject): YamlValue = jso.fields.toYaml 

    override 
    def read(yv: YamlValue): JsObject = yv.convertTo[JsValue] match { 
     case jso: JsObject => jso 
     case x => my.deserializationError(s"Expected YAML object, got: $x") 
    } 
    } 
} 

我已經測試了這個。如果有人想看,請說。

+0

如果一切正常,也許你應該發佈一個jar到maven倉庫;)。 –

+0

我想了解如何更好地處理'YamlNumber'的情況。這方面與JSON略有不同。 – akauppi

+1

發表了一篇關於「YamlNumber」轉換的公關問題:https://github.com/jcazevedo/moultingyaml/pull/20 – akauppi