2013-05-12 7 views
9

में कनवर्ट करें मैं जेएसन और बैक में कनवर्ट करते समय Ec2Provider और OpenstackProvider के बीच की पसंद को पहचानने के लिए स्काला में स्प्रे-जेसन का उपयोग करने की कोशिश कर रहा हूं। मैं "प्रदाता" में विकल्प देने में सक्षम होना चाहता हूं, और यदि वे विकल्प उपलब्ध लोगों के अनुरूप नहीं हैं तो इसे मान्य नहीं करना चाहिए।पॉलीमोर्फिक केस क्लास को जेसन और वापस

इस पर मेरे प्रयास के बाद कोड में देखा जा सकता:

import spray.json._ 
import DefaultJsonProtocol._ 

case class Credentials(username: String, password: String) 
abstract class Provider 
case class Ec2Provider(endpoint: String,credentials: Credentials) extends Provider 
case class OpenstackProvider(credentials: Credentials) extends Provider 
case class Infrastructure(name: String, provider: Provider, availableInstanceTypes: List[String]) 
case class InfrastructuresList(infrastructures: List[Infrastructure]) 

object Infrastructures extends App with DefaultJsonProtocol { 
    implicit val credFormat = jsonFormat2(Credentials) 
    implicit val ec2Provider = jsonFormat2(Ec2Provider) 
    implicit val novaProvider = jsonFormat1(OpenstackProvider) 
    implicit val infraFormat = jsonFormat3(Infrastructure) 
    implicit val infrasFormat = jsonFormat1(InfrastructuresList) 

    println(
    InfrastructuresList(
     List(
     Infrastructure("test", Ec2Provider("nova", Credentials("user","pass")), List("1", "2")) 
    ) 
    ).toJson 
) 
} 

दुर्भाग्य से, यह विफल रहता है, क्योंकि यह Provider सार वर्ग के लिए एक फ़ॉर्मेटर नहीं मिल रहा।

test.scala:19: could not find implicit value for evidence parameter of type Infrastructures.JF[Provider] 

किसी के पास इसका कोई समाधान है?

उत्तर

14

आप जो करना चाहते हैं वह बॉक्स से बाहर नहीं है (यानी कुछ प्रकार के संकेतों के माध्यम से जो deserializer को यह जानने के लिए कि ठोस वर्ग को तत्काल करने के लिए क्या अनुमति है), लेकिन यह निश्चित रूप से छोटे पैर के काम के साथ संभव है। सबसे पहले, उदाहरण के लिए, कोड का एक सरलीकृत संस्करण का उपयोग कर आप ऊपर पोस्ट:

case class Credentials(user:String, password:String) 
abstract class Provider 
case class Ec2Provider(endpoint:String, creds:Credentials) extends Provider 
case class OpenstackProvider(creds:Credentials) extends Provider 
case class Infrastructure(name:String, provider:Provider) 

object MyJsonProtocol extends DefaultJsonProtocol{ 
    implicit object ProviderJsonFormat extends RootJsonFormat[Provider]{ 
    def write(p:Provider) = p match{ 
     case ec2:Ec2Provider => ec2.toJson 
     case os:OpenstackProvider => os.toJson 
    } 

    def read(value:JsValue) = value match{ 
     case obj:JsObject if (obj.fields.size == 2) => value.convertTo[Ec2Provider] 
     case obj:JsObject => value.convertTo[OpenstackProvider] 
    } 
    } 

    implicit val credFmt = jsonFormat2(Credentials) 
    implicit val ec2Fmt = jsonFormat2(Ec2Provider) 
    implicit val openStackFmt = jsonFormat1(OpenstackProvider) 
    implicit val infraFmt = jsonFormat2(Infrastructure) 
} 

object PolyTest { 
    import MyJsonProtocol._ 

    def main(args: Array[String]) { 
    val infra = List(
     Infrastructure("ec2", Ec2Provider("foo", Credentials("me", "pass"))), 
     Infrastructure("openstack", OpenstackProvider(Credentials("me2", "pass2"))) 
    ) 
    val json = infra.toJson.toString 
    val infra2 = JsonParser(json).convertTo[List[Infrastructure]] 
    println(infra == infra2) 
    } 
} 

आदेश क्रमानुसार करने अमूर्त वर्ग Provider की/deserialize उदाहरणों सक्षम होने के लिए, मैं मैं कहाँ की आपूर्ति कर रहा हूँ एक कस्टम फ़ॉर्मेटर बना लिया है Provider उदाहरण पढ़ने और लिखने के लिए संचालन। मैं इन कार्यों में कर रहा हूं हालांकि यह एक साधारण स्थिति की जांच कर रहा है (यहां बाइनरी है क्योंकि Provider के केवल 2 इम्प्ले हैं) यह देखने के लिए कि यह किस प्रकार है और फिर उस प्रकार को संभालने के लिए तर्क में प्रतिनिधि।

लेखन के लिए, मुझे बस यह जानने की आवश्यकता है कि यह किस प्रकार का उदाहरण है जो आसान है। हालांकि पढ़ना थोड़ा मुश्किल है। पढ़ने के लिए, मैं जांच रहा हूं कि ऑब्जेक्ट के कितने गुण हैं और चूंकि दोनों इम्प्लों में प्रोप की अलग-अलग संख्याएं हैं, इसलिए मैं इस तरह से भिन्नता कर सकता हूं। जिस चेक को मैं यहां बना रहा हूं वह बहुत ही प्राथमिक है, लेकिन यह इस बिंदु को दिखाता है कि यदि आप जेसन एएसटी को देख सकते हैं और प्रकारों को अलग कर सकते हैं, तो आप इसे चुनने के लिए कौन सा चुन सकते हैं। आपकी वास्तविक जांच जितनी चाहें उतनी सरल या जटिल हो सकती है, जब तक कि यह प्रकारों को अलग करने में निर्धारक है।

+0

आप से बहुत ज्यादा! मुझे ठीक इसी की आवश्यकता थी! – wernerb

संबंधित मुद्दे