使用MoultingYaml将{YAML转换为JSON /从JSON转换

时间:2016-11-24 21:08:48

标签: json scala yaml snakeyaml

MoultingYaml对于YAML来说是一个类似于spray.json的东西,非常有益。

但是,它没有为转换YAML< - >提供现成的支持。 JSON。我认为这样有用,至少作为使用例如的示例代码。 spray.json认为该项目与之密切相关。

如果有人提示/制作如此简洁的代码,谢谢。如果没有,我可能会在这里发布并发布它。

2 个答案:

答案 0 :(得分:1)

这就是我想出来的。

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

我已经对此进行了测试。如果有人想看,请说。

答案 1 :(得分: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] = spray.json.ProductFormatsInstances$$anon$1@6b9fc143                                       

scala> implicit val TestAsYaml = yamlFormat1(Test)                                                                                      
TestAsYaml: net.jcazevedo.moultingyaml.YamlFormat[Test] = net.jcazevedo.moultingyaml.ProductFormats$$anon$23@151806b4                   

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                                                                                                                                
}