2013-08-26 2 views
16

मैं अक्सर क्रमानुसार करने की है/deserialize योग प्रकार (जैसे Either[S,T]), और मैं नहीं अभी तक एक सामान्य या सुरुचिपूर्ण तरीका यह करने के लिए मिल गया है। यहाँ एक उदाहरण प्रकार (अनिवार्य रूप से Either के बराबर)Json क्रमबद्धता एकाधिक मामला वर्ग (योग प्रकार) स्काला के प्ले में

sealed trait OutcomeType 
case class NumericOutcome(units: String)    extends OutcomeType 
case class QualitativeOutcome(outcomes: List[String]) extends OutcomeType 

यहाँ एक साथी उद्देश्य यह है कि क्रमबद्धता को लागू करता है पर मेरे सबसे अच्छे प्रयास है। यह काम करता है, लेकिन यह हर योग प्रकार के लिए अधिक से अधिक चीजों की इन प्रकार के लिखने के लिए बहुत थकाऊ है। क्या यह अच्छा और/या अधिक सामान्य बनाने के लिए कोई सुझाव है?

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 

object OutcomeType { 

    val fmtNumeric  = Json.format[NumericOutcome] 
    val fmtQualitative = Json.format[QualitativeOutcome] 

    implicit object FormatOutcomeType extends Format[OutcomeType] { 
    def writes(o: OutcomeType) = o match { 
     case [email protected](_)  => Json.obj("NumericOutcome"  -> Json.toJson(n)(fmtNumeric)) 
     case [email protected](_) => Json.obj("QualitativeOutcome" -> Json.toJson(q)(fmtQualitative)) 
    } 

    def reads(json: JsValue) = (
     Json.fromJson(json \ "NumericOutcome")(fmtNumeric) orElse 
     Json.fromJson(json \ "QualitativeOutcome")(fmtQualitative) 
    ) 
    } 
} 
+0

आप की कोशिश की है json4s http://json4s.org? इसके अलावा, आप खेलने के साथ उपयोग करना चाहते हैं तो आप यहां दिखना चाहिए: https://github.com/tototoshi/play-json4s या इस खुद को लागू। –

+0

मेरे लिए अच्छा लग रहा है। क्या आप play2.5 के लिए अपना सर्वश्रेष्ठ प्रयास अपडेट कर सकते हैं? धन्यवाद! – qed

+0

कोई बात नहीं, मुझे पता चला कैसे play2.5 में यह कर और एक जवाब में यह डाल करने के लिए। – qed

उत्तर

0

मुझे लगता है कि के बारे में के रूप में सरल है के रूप में आप यह कर सकते हैं, यदि आप हो सकता है आप प्रतिबिंब के साथ यह कर सकता है प्रत्येक स्पष्ट उप-प्रकार के लिए कोड लिखने से बचना चाहते हैं, सीधे जैक्सन का उपयोग करें या प्रतिबिंब के साथ कुछ अन्य json पुस्तकालय समर्थन। या उपप्रकारों की सूची से प्रारूप उत्पन्न करने के लिए अपना खुद का मैक्रो लिखें।

0

मैं अपने json अचार बनाने पुस्तकालय Prickle में योग-प्रकार serializing की समस्या के लिए एक व्यवस्थित समाधान है। इसी तरह के विचारों को प्ले के साथ नियोजित किया जा सकता है। अभी भी कुछ config आवश्यक कोड है, लेकिन इसके उच्च संकेत/शोर, जैसे अंतिम कोड की तरह:

implicit val fruitPickler = CompositePickler[Fruit].concreteType[Apple].concreteType[Lemon]

CompositePicklers एक महाप्रकार के साथ जुड़े प्रत्येक में जाना जाता उप-प्रकार के लिए एक PicklerPair (यानी योग प्रकार विकल्प) के साथ कॉन्फ़िगर किया गया है। एसोसिएशन कॉन्फ़िगरेशन समय पर सेट हैं।

pickling के दौरान एक विवरणक json धारा का वर्णन है जो उप-प्रकार रिकॉर्ड है में उत्सर्जित होता है।

unpickling के दौरान, वर्णनकर्ता json से बाहर पढ़ने के लिए है और फिर उप प्रकार

0

एक उदाहरण खेलने 2.5 के लिए अद्यतन के लिए उपयुक्त Unpickler पता लगाने के लिए इस्तेमाल किया:

object TestContact extends App { 

    sealed trait Shape 

    object Shape { 
    val rectFormat = Json.format[Rect] 
    val circleFormat = Json.format[Circle] 

    implicit object ShapeFormat extends Format[Shape] { 
     override def writes(shape: Shape): JsValue = shape match { 
     case rect: Rect => 
      Json.obj("Shape" -> 
      Json.obj("Rect" -> 
       Json.toJson(rect)(rectFormat))) 
     case circle: Circle => 
      Json.obj("Shape" -> 
      Json.obj("Circle" -> 
       Json.toJson(circle)(circleFormat))) 
     } 

     override def reads(json: JsValue): JsResult[Shape] = { 
     json \ "Shape" \ "Rect" match { 
      case JsDefined(rectJson) => rectJson.validate[Rect](rectFormat) 
      case _ => json \ "Shape" \ "Circle" match { 
      case JsDefined(circleJson) => circleJson.validate[Circle](circleFormat) 
      case _ => JsError("Not a valide Shape object.") 
      } 
     } 
     } 
    } 

    } 

    case class Rect(width: Double, height: Double) extends Shape 

    case class Circle(radius: Double) extends Shape 

    val circle = Circle(2.1) 
    println(Json.toJson(circle)) 
    val rect = Rect(1.3, 8.9) 
    println(Json.toJson(rect)) 

    var json = Json.obj("Shape" -> Json.obj("Circle" -> Json.obj("radius" -> 4.13))) 
    println(json.validate[Shape]) 
    json = 
    Json.obj("Shape" -> 
     Json.obj("Rect" -> 
     Json.obj("width" -> 23.1, "height" -> 34.7))) 
    println(json.validate[Shape]) 
} 
संबंधित मुद्दे