2013-06-27 4 views
5

मैं स्केलैट्रा का उपयोग कर रहा हूं, लेकिन यह प्रश्न किसी भी स्कैला प्रोग्रामिंग के लिए मान्य होना चाहिए। मैं रेल पृष्ठभूमि पर रूबी से आया हूं।जेएसओएन और/या एक्सएमएल टेम्पलेट्स का उपयोग कर स्कैला

Jbuilder.encode do |json| 
    json.content format_content(@message.content) 
    json.(@message, :created_at, :updated_at) 

    json.author do 
    json.name @message.creator.name.familiar 
    json.email_address @message.creator.email_address_with_name 
    json.url url_for(@message.creator, format: :json) 
    end 

    if current_user.admin? 
    json.visitors calculate_visitors(@message) 
    end 

    json.comments @message.comments, :content, :created_at 

    json.attachments @message.attachments do |attachment| 
    json.filename attachment.filename 
    json.url url_for(attachment) 
    end 
end 

: सीधे शब्दों में कहें, जैसे XML बिल्डर या jsonbuilder (https://github.com/rails/jbuilder) के रूप में templating सिस्टम का उपयोग कर, मैं जैसे कि निम्न खाका बनाते समय के आधार पर अपने JSON या एक RESTful API में XML आउटपुट होगा क्या पर पूरा नियंत्रण था यहां आदर्श है, मैंने नियंत्रक + एक्शन में जो भी तर्क आवश्यक है, उसके साथ @message ऑब्जेक्ट को एक साथ रखा है। यह एक टेम्पलेट को पास हो जाता है जिसमें if current_user.admin? जैसे तर्क शामिल हैं, अन्यथा कुछ नहीं।

स्केल या स्केलैट्रा में समान समकक्ष उपकरण क्या है जो कुछ ऐसा करने के लिए उपलब्ध है? मुझे पता है कि serializer मुझे जेएसओएन या एक्सएमएल को किसी विशेष मॉडल से जेनरेट करने देता है, लेकिन रुबी में यह वही बात है (अगर मैं गलत हूं तो सही है) as_json या as_xml ओवरराइडिंग के रूप में। कभी-कभी, टेम्पलेट्स अधिक जटिल होते हैं और कई मॉडल, डेटा की विशिष्ट संरचना, डेटा के विशिष्ट क्रम आदि शामिल हैं। यह मुझे लचीलापन की आवश्यकता है। क्या कोई ऐसा उपकरण है जो स्कैला/स्केलेट्रा पर्यावरण में ऐसे टेम्पलेटिंग की अनुमति देता है?

उत्तर

4

दुर्भाग्यवश मुझे एक्सएमएल में ऐसा करने के लिए वास्तव में कोई अच्छी लाइब्रेरी नहीं पता (हालांकि Anti-Xml एक नज़र डालने लायक है)। लेकिन वहाँ Json के लिए इस तरह के पुस्तकालय हैं और यह, PlayJson खेलने json के साथ आप मूल रूप से सब कुछ आप रूबी के JsBuilder साथ कर सकते हैं क्या कर सकते हैं कुछ प्रतिमान अंतर को छोड़कर:

  1. स्काला संभव है और कई कई के रूप में के रूप में कार्यक्षम होने की कोशिश करता है पुस्तकालय अनावश्यक डेटा संरचनाओं के साथ काम करते हैं। जेसन खेलें अपवाद नहीं है। इसका मतलब यह है कि आप बस कुछ json पेड़ में गहरी मूल्य नहीं बदल सकते हैं, आप पूरे json वस्तु

  2. स्काला एक स्थिर टाइप किया भाषा है फिर से संगठित करने की जरूरत है। जो महान है, क्योंकि संकलक शुद्धता के लिए सभी प्रकार-हस्ताक्षर जांचता है, सिवाय इसके कि हमें उन हस्ताक्षरों को प्रदान करना होगा।

यहाँ उदाहरण कोड है:

import org.joda.time.DateTime 
import org.joda.time.format.DateTimeFormat 

case class Attachment(fileName: String, url: String) 
case class Author(name: String, email: String, url: String) 
case class Comment(content: String, created_at: DateTime) 
case class Post(author: Author, content: String, attachments: List[Attachment], comments: List[Comment], created_at: DateTime, updated_at: DateTime) 

object Main { 

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

    val isAdmin = true 

    def calculateVisits(post: Post) = 35 

    implicit val jodaTimeWrites: Writes[DateTime] = new Writes[DateTime] { 
    def writes(c: DateTime): JsValue = { 
     Json.toJson(c.toString(DateTimeFormat.fullDateTime())) 
    } 
    } 
    implicit val attachmentFormat = Json.format[Attachment] 

    implicit val authorWrites: Writes[Author] = (
    (__ \ "name").write[String] and 
    (__ \ "email").write[String] and 
    (__ \ "url").write[String]) { unlift(Author.unapply) } 

    implicit val commentWrites: Writes[Comment] = (
    (__ \ "content").write[String] and 
    (__ \ "created_at").write[DateTime]) { unlift(Comment.unapply) } 

    implicit val postWrites: Writes[Post] = (
    (__ \ "content").write[String] and 
    (__ \ "created_at").write[DateTime] and 
    (__ \ "updated_at").write[DateTime] and 
    (__ \ "author").write[Author] and 
    (__ \ "visitors").write[Option[Int]] and 
    (__ \ "comments").write[List[Comment]] and 
    (__ \ "attachments").write[List[Attachment]]) { post: Post => 
     (
     post.content, 
     post.created_at, 
     post.updated_at, 
     post.author, 
     if (isAdmin) Some(calculateVisits(post)) else None, 
     post.comments, 
     post.attachments) 
    } 

    def main(args: Array[String]): Unit = { 
    val post = Post(
     Author("David H.", "[email protected]", "http://example.com/users/1-david.json"), 
     "<p>This is <i>serious</i> monkey business</p>", 
     List(
     Attachment("forecast.xls", "http://example.com/downloads/forecast.xls"), 
     Attachment("presentation.pdf", "http://example.com/downloads/presentation.pdf")), 
     List(
     Comment("Hello everyone!", new DateTime()), 
     Comment("To you my good sir!", new DateTime())), 
     new DateTime(), 
     new DateTime()) 

    Console println (Json prettyPrint (Json toJson post)) 
    } 

} 

सूचना attachmentFormat - यह स्केला मैक्रो द्वारा उत्पन्न होता है मामले वर्ग परिभाषा के साथ मिलान किया जाना है। मेरी परियोजना में मैंने कभी भी एक मैनुअल प्रारूप ओवरराइड संकलक नहीं लिखा है मेरे लिए सभी प्रारूप उत्पन्न करता है! लेकिन अगर मुझे जरूरत है तो मैं कर सकता हूं। अच्छा उदाहरण jodaTimeWrites है - डिफ़ॉल्ट जोडाटाइमफॉर्मैट लंबे मूल्य उत्पन्न करेगा जो मशीन प्रसंस्करण के लिए अधिक उपयुक्त है, लेकिन मैंने इसे रूबी के नमूने से मेल खाने के लिए अपने स्वयं के निहित प्रारूप के साथ ओवरराइड कर दिया है।

कोड ऊपर उत्पादन निम्नलिखित का उत्पादन: गहरे लाल रंग का कोड की

अब 21 के बजाय
{ 
    "content" : "<p>This is <i>serious</i> monkey business</p>", 
    "created_at" : "Friday, July 5, 2013 4:19:42 PM +03:00", 
    "updated_at" : "Friday, July 5, 2013 4:19:42 PM +03:00", 
    "author" : { 
    "name" : "David H.", 
    "email" : "[email protected]", 
    "url" : "http://example.com/users/1-david.json" 
    }, 
    "visitors" : 35, 
    "comments" : [ { 
    "content" : "Hello everyone!", 
    "created_at" : "Friday, July 5, 2013 4:19:42 PM +03:00" 
    }, { 
    "content" : "To you my good sir!", 
    "created_at" : "Friday, July 5, 2013 4:19:42 PM +03:00" 
    } ], 
    "attachments" : [ { 
    "fileName" : "forecast.xls", 
    "url" : "http://example.com/downloads/forecast.xls" 
    }, { 
    "fileName" : "presentation.pdf", 
    "url" : "http://example.com/downloads/presentation.pdf" 
    } ] 
} 

लाइनों मैं किसी भी तरह अधिक जटिल मैपिंग स्केला के 33 लाइनों मिल गया (जैसा भी मामला वर्गों के बिना)। और क्यों टाइप करें? क्योंकि अब मैं निश्चित रूप से मर चुका हूं कि जब मैं Attachment के बजाय Comment पास करता हूं तो मुझे कंपाइलर त्रुटि मिल जाएगी, या जब मेरे सहयोगी गलती से बदल जाएंगे joda.time.DateFormat java.util.DateFormat को कुछ गड़बड़ के बजाय त्रुटि प्राप्त होगी ।

0

यहाँ एक जवाब का उपयोग करने का एक स्केच है स्काला के अंतर्निहित एक्सएमएल शाब्दिक और उत्कृष्ट argonaut.io JSON क्रमबद्धता पुस्तकालय:

// dependencies for use with scala 2.10.2: 
// "io.argonaut" %% "argonaut" % "6.0-RC3" 
// "org.scalaz" %% "scalaz-core" % "7.0.1" 

import scalaz._, Scalaz._ 
import argonaut._, Argonaut._ 

object ArgonautJsonExample extends App { 

    case class File(name: String, url: String = "http://my.dummy.url") 
    case class Message(name: String, isAdmin: Boolean, attachmentOpt: Option[File]) 
    val message = 
    new Message(
     "Erik", 
     true, 
     Some(File("strawberry.png")) 
    ) 

    val json: Json = 
    ("name" := message.name) ->: 
    ("filename" :=? message.attachmentOpt.map(_.name)) ->?: 
    ("url" :=? message.attachmentOpt.map(_.url)) ->?: 
    jEmptyObject 


    val myXml = 
    <myObject> 
     <author> 
     <name>{message.name}</name> 
     </author> 
     { 
     message.attachmentOpt map { file => 
      <attachment url={file.url}> 
      {file.name} 
      </attachment> 
     } getOrElse xml.NodeSeq.Empty 
     } 
    </myObject> 


    println("json = " + json) 
    println("") 
    println("xml = " + myXml) 

} 

हो जाएगा ताकि आप दे देंगे:

json = {"url":"http://my.dummy.url","filename":"strawberry.png","name":"Erik"} 

xml = <myObject> 
    <author> 
    <name>Erik</name> 
    </author> 
    <attachment url="http://my.dummy.url"> 
     strawberry.png 
     </attachment> 
</myObject> 
संबंधित मुद्दे