2016-11-24 6 views
1

MoultingYaml은 YAML의 모양이 비슷하고 그로 인해 매우 유용합니다.MoultingYaml을 사용하여 JSON에서 JSON으로 변환/변환

그러나 YAML < -> JSON을 변환하기위한 기성품 지원은 제공하지 않습니다. 적어도, 예를 들어, 코드를 사용하는 샘플 코드로서 유용 할 것이라고 생각합니다. spray.json 프로젝트가 밀접하게 관련되어 있습니다.

간단한 코드 작성에 대한 힌트가 있거나 도움이되는 사람이 있으면 감사합니다. 그렇지 않다면 아마 여기에 나와서 게시 할 것입니다.

답변

0

YAML/JSON을 중간 스칼라 객체 형식으로 변환 할 수 있습니다. 뭐 그런 :

여기
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과 같은 메서드는 그 때문에 해결하기가 어렵습니다.

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

이 내가 생각 해낸 것입니다 : listFormat 같은 수입 등,

있을 때 약간 청소기 적은 충돌 모호한된다.

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

모든 것이 잘 작동한다면 병을 저장소에 게시해야합니다.). –

+0

'YamlNumber' 사례를 더 잘 수행하는 방법에 대한 아이디어를 얻고 싶습니다. JSON과 약간 다릅니다. – akauppi

+1

'YamlNumber'변환에 대해 묻는 PR 게시 : https://github.com/jcazevedo/moultingyaml/pull/20 – akauppi