2013-10-07 7 views
5

मैं स्कैला-पिकलिंग की वर्तमान सीमाओं के आसपास काम करने के लिए एक कस्टम स्पिकलर/अनपिक्लर जोड़ी लिखने की कोशिश कर रहा हूं। डेटा प्रकार जिसे मैं अचार करने की कोशिश कर रहा हूं वह एक केस क्लास है, जहां कुछ फ़ील्ड में पहले से ही अपने स्वयं के स्पिकलर और अनपिक्लर उदाहरण हैं। मैं अपने कस्टम पिकलर में इन उदाहरणों का उपयोग करना चाहता हूं, लेकिन मुझे नहीं पता कि कैसे।स्कैला पिकलिंग: नेस्टेड संरचनाओं के लिए कस्टम पिकलर/अनपिकरर लिखना

// Here's a class for which I want a custom SPickler/Unpickler. 
// One of its fields can already be pickled, so I'd like to reuse that logic. 
case class MyClass[A: SPickler: Unpickler: FastTypeTag](myString: String, a: A) 

// Here's my custom pickler. 
class MyClassPickler[A: SPickler: Unpickler: FastTypeTag](
    implicit val format: PickleFormat) extends SPickler[MyClass[A]] with Unpickler[MyClass[A]] { 
    override def pickle(
    picklee: MyClass[A], 
    builder: PBuilder) { 
    builder.beginEntry(picklee) 

    // Here we save `myString` in some custom way. 
    builder.putField(
     "mySpecialPickler", 
     b => b.hintTag(FastTypeTag.ScalaString).beginEntry(
     picklee.myString).endEntry()) 

    // Now we need to save `a`, which has an implicit SPickler. 
    // But how do we use it? 

    builder.endEntry() 
    } 

    override def unpickle(
    tag: => FastTypeTag[_], 
    reader: PReader): MyClass[A] = { 
    reader.beginEntry() 

    // First we read the string. 
    val myString = reader.readField("mySpecialPickler").unpickle[String] 

    // Now we need to read `a`, which has an implicit Unpickler. 
    // But how do we use it? 
    val a: A = ??? 

    reader.endEntry() 

    MyClass(myString, a) 
    } 
} 

मैं वास्तव में एक काम कर उदाहरण का स्वागत करेंगे:

यहाँ मैं क्या मतलब का एक उदाहरण है। धन्यवाद!

case class MyClass[A](myString: String, a: A) 

ध्यान दें कि MyClass के प्रकार के पैरामीटर संदर्भ सीमा की जरूरत नहीं है:

उत्तर

5

यहाँ एक काम कर उदाहरण है। केवल कस्टम पिकलर वर्ग इसी implicits की जरूरत है:

class MyClassPickler[A](implicit val format: PickleFormat, aTypeTag: FastTypeTag[A], 
            aPickler: SPickler[A], aUnpickler: Unpickler[A]) 
    extends SPickler[MyClass[A]] with Unpickler[MyClass[A]] { 

    private val stringUnpickler = implicitly[Unpickler[String]] 

    override def pickle(picklee: MyClass[A], builder: PBuilder) = { 
    builder.beginEntry(picklee) 

    builder.putField("myString", 
     b => b.hintTag(FastTypeTag.ScalaString).beginEntry(picklee.myString).endEntry() 
    ) 

    builder.putField("a", 
     b => {  
     b.hintTag(aTypeTag) 
     aPickler.pickle(picklee.a, b) 
     } 
    ) 

    builder.endEntry() 
    } 

    override def unpickle(tag: => FastTypeTag[_], reader: PReader): MyClass[A] = { 
    reader.hintTag(FastTypeTag.ScalaString) 
    val tag = reader.beginEntry() 
    val myStringUnpickled = stringUnpickler.unpickle(tag, reader).asInstanceOf[String] 
    reader.endEntry() 

    reader.hintTag(aTypeTag) 
    val aTag = reader.beginEntry() 
    val aUnpickled = aUnpickler.unpickle(aTag, reader).asInstanceOf[A] 
    reader.endEntry() 

    MyClass(myStringUnpickled, aUnpickled) 
    } 

} 

कस्टम पिकलर वर्ग के अलावा, हम भी एक अंतर्निहित डीईएफ़ जो एक पिकलर उदाहरण ठोस प्रकार तर्क के लिए विशेष रिटर्न की जरूरत है:

implicit def myClassPickler[A: SPickler: Unpickler: FastTypeTag](implicit pf: PickleFormat) = 
    new MyClassPickler 
+0

यह काम करता है , लेकिन एक अजीब असममितता है: 'अचार' में, फ़ील्ड का नाम 'builder.putField ("myString", ...)' के रूप में रखा गया है, लेकिन हम उन नामों का उपयोग 'अनपिक्ले' में नहीं करते हैं। क्या ये नाम वैकल्पिक हैं, और यदि हां, तो हम उनका उपयोग कैसे कर सकते हैं? – emchristiansen

+0

जेएसओएन जैसे कुछ अचार प्रारूपों ने क्षेत्र के नाम को अचार में रखा। यहां तक ​​कि यदि कभी-कभी उनका उपयोग नहीं किया जाता है, तो वर्तमान में उनका उपयोग करने से बचने का कोई तरीका नहीं है। एपीआई अभी भी थोड़ा विकसित हो रहा है, हालांकि। –

+0

यह सामान केवल बाइनरी के लिए जेसन के लिए काम नहीं करेगा। – Yar

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