Leider kenne ich keine wirklich gute Bibliothek, um dies in XML zu tun (obwohl Anti-Xml einen Blick wert ist). Aber es gibt solche Bibliothek für Json und es ist das PlayJson Mit Spiel json können Sie im Grunde alles tun Sie mit Rubys JSBuilder tun können, mit Ausnahme einiger Paradigma Unterschied:
Scala versucht, so funktional wie möglich zu sein, und viele viele Bibliotheken arbeiten mit unveränderbaren Datenstrukturen. Play Json ist keine Ausnahme. Dies bedeutet, dass Sie nicht einfach einen Wert tief in der JSON-Struktur ändern können, müssen Sie das gesamte JSON-Objekt zu rekonstruieren
Scala ist eine statisch typisierte Sprache. Das ist großartig, weil der Compiler alle Typ-Signaturen auf Korrektheit überprüft, außer dass wir diese Signaturen bereitstellen müssen.
Hier ist Beispielcode:
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))
}
}
Beachten Sie die attachmentFormat
- durch scala Makros erzeugt wird mit Fallklassendefinition angepasst werden. In meinem Projekt habe ich noch nie ein einziges Handbuch geschrieben. Format Override Compiler erzeugt alle Formate für mich! Aber ich kann, wenn ich muss. Ein gutes Beispiel ist die jodaTimeWrites
- default jodaTimeFormat erzeugt einen langen Wert, der für die Maschinenverarbeitung besser geeignet ist, aber ich habe ihn mit meinem eigenen impliziten Format überschrieben, um Rubys Sample zu vergleichen.
Der obige Code erzeugt folgende Ausgabe:
{
"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"
} ]
}
nun statt 21 Zeilen von Ruby-Code habe ich 33 Zeilen von Scalas irgendwie komplizierten Mappings (ohne Fallklassen). Warum mehr tippen? Denn jetzt bin ich todsicher, dass wenn ich Comment
statt Attachment
übergebe, bekomme ich einen Compilerfehler, oder wenn mein Kollege irrtümlicherweise joda.time.DateFormat zu java.util.DateFormat ändert, wird er statt eines Kauderwelschs Fehler bekommen .