加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala使用JSON和/或XML模板

发布时间:2020-12-16 18:38:29 所属栏目:安全 来源:网络整理
导读:我正在使用 Scalatra,但这个问题应该适用于任何Scala编程.我来自 Ruby on Rails背景.简单地说,使用XML Builder或jsonbuilder( https://github.com/rails/jbuilder)等模板系统,我可以通过创建如下模板来完全控制RESTful API中的JSON或XML输出: Jbuilder.enco
我正在使用 Scalatra,但这个问题应该适用于任何Scala编程.我来自 Ruby on Rails背景.简单地说,使用XML Builder或jsonbuilder( https://github.com/rails/jbuilder)等模板系统,我可以通过创建如下模板来完全控制RESTful API中的JSON或XML输出:

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

这里的理想是,我将@message对象与控制器动作中所需的任何逻辑放在一起.那会被传递给一个具有逻辑的模板,例如if current_user.admin?包括一些东西,否则不包括.

什么是Scala或Scalatra中可用的类似工具?我知道序列化程序会让我覆盖从特定模型生成的JSON或XML,但这与Ruby中的相同(如果我错了,请纠正我)作为重写as_json或as_xml.然而,有时候,模板要复杂得多,包括多个模型,特定的数据结构,特定的数据排序等.这就是我需要的灵活性.目前有一个工具可以在Scala / Scalatra环境中进行这样的模板化吗?

解决方法

不幸的是,我不知道用XML做任何真正好的库(尽管 Anti-Xml值得一看).但Json有这样的图书馆,它是 PlayJson
使用play json,除了一些范例差异外,你基本上可以用Ruby的JsBuilder完成所有事情:

> Scala尽可能地发挥功能,许多库使用不可变数据结构.玩json也不例外.这意味着你不能只在json树中更改一些值,你需要重建整个json对象
> Scala是一种静态类型语言.这很好,因为编译器会检查所有类型签名的正确性,除非我们必须提供这些签名.

这是示例代码:

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.","david@heinemeierhansson.com","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 – 它由scala宏生成,以与case类定义匹配.在我的项目中,我从未编写过单一的手动格式覆盖编译器为我生成所有格式!但我可以,如果我需要.好的例子是jodaTimeWrites – 默认的jodaTimeFormat将生成更长的值,这更适合于机器处理,但我用我自己的隐式格式覆盖它以匹配ruby的样本.

上面的代码产生以下输出:

{
  "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,"author" : {
    "name" : "David H.","email" : "david@heinemeierhansson.com","url" : "http://example.com/users/1-david.json"
  },"visitors" : 35,"comments" : [ {
    "content" : "Hello everyone!",2013 4:19:42 PM +03:00"
  },{
    "content" : "To you my good sir!",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"
  } ]
}

现在代替21行ruby代码,我得到了33行scala,不知怎的更复杂的映射(没有case类).为何选择更多?因为现在我已经确定当我通过Comment而不是Attachment时我会遇到编译器错误,或者当我的同事将joda.time.DateFormat更改为java.util.DateFormat时,他会收到错误而不是一些乱码.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读