Rails 用啥来 render json ?

larryzhao · 2013年07月30日 · 最后由 what_is_ruby 回复于 2013年10月29日 · 8141 次阅读
本帖已被设为精华帖!

最近在搭一些 api, 免不了就要 render json 了, 本来一直是用的 rabl , 因为 json 场景不多, 所以也无所谓了。但现在要正经搞 api 了, 所以还是要花点心思。

网上搜了一下, 基本上就是三种

然后网上搜了一下又看到了一大牛的推和下面的评论:

然后我就自己简单测了一下, 在我自己机器上 render 4w多个 model 的数组, 每个 object 就只 render 一个 id attribute. 每种 render 方法用 curl call 了20次, 统计了一下 development.log 里面 view render 的时间取平均值:

  • rabl: 743 ms
  • jbuilder: 445 ms
  • serializer: 1306 ms

jbuilder 明显胜出, 求问一下, 是我什么地方用的不对么? 还是大牛去年9月份说的已经 out of date 了, 现在的确是 jbuilder 最好?

环境是 Rails 3.2, rabl 0.8.4, jbuilder 1.5.0, active_model_serializers 0.8.1, ruby-1.9.3-p327-falcon, Mac OSX 10.8.4


UPDATE

把数据量增大测试了一次, 这次 render 了 1080 个『简书』的长文的数组, 每个 object 都包含了很长的全文, 和数组类型。因为有全文数据大实在有点慢, 只跑了 10 次取平均:

  • rabl: 5625 ms
  • jbuilder: 5450 ms
  • serializer: 14112 ms

jbuilder 和 rabl 可以说基本没有差别, serializer 太慢了, 不知道是不是我哪里写的不对。不过 serializer 里面不能直接用 helper method 对我现在来说很不方便。

共收到 38 条回复

看star数,群众的眼睛是雪亮的。

我用 jbuilder, 集成在rails4 里了. 相信大牛.

@hooopo rabl 2319, jbuilder 1127, active_model_serializers 1362.

我最开始也是因为star数选rabl的, 但是简单测下来 jbuilder 最快, 我正在多放点儿属性再测一下

#2楼 @zgm 作者都是大牛呀..

  • rabl作者是padrino的作者
  • jbuilder作者是dhh
  • active model serialiers代码贡献最多的是yahuda

#2楼 @zgm 集成到Rails4里说明不了什么,一般用json模板都是做API服务器,Rails做API服务器没有一点优势。

PS. rabl支持JSONP,这点符合我的胃口。

我们的项目里用着active_model_serializers,我正在考虑把它换掉。除了慢之外,active_model_serializers的设计思想可能就是一个model对应一个serializer,但实际应用中,同一个model在不同的view中需要的字段可能有很大差别。active_model_serializers不容易解决这个问题。

@yanhao 可以对应不同的serializer

render :json => @note, :serializer => Api::V1::NoteSerializer, :root => false render :json => @notes, :each_serializer => Api::V1::NoteSerializer, :root => false

这样就好了

我用 jbuilder,要什么写什么,直观。

@Rei jbuilder 和 serializer 写起来的确要比 rabl 舒服

#8楼 @Rei 按这种说法,最直观的是to_json

#10楼 @hooopo to_json 可定制性太弱了。。。

#10楼 @hooopo 之前用过 rabl 和 jbuilder.. jbuilder 比 rabl 要直观很多, 尤其是要合并 model 输出或者插入外部字段的时候.. rabl 我完全就不会了.. 后来就换 jbuilder 了. 当然如果不需要控制 json 的输出结果, 那肯定直接 to_json 就好了, 整这么多没用的干嘛...

#12楼 @Saito 这样?

object false
node(:some_count) { |m| @user.posts.count }
child(@user) { attribute :name }

#11楼 @googya 所以要综合比较呀

@hooopo 总觉 rabl DSL 看起来不如那俩易读, 而且 exception 之后 log 里面 jbuilder 看起来也直观点儿

#13楼 @hooopo 忘记了, 快两年了... 如果要在 user root 里面插入 @user.posts.count 呢?

在 jbuilder 下面你可以在 任何节点随便插入什么属性.. 在 rabl 里面你要想一下该怎么插入. 这就是他们的区别.

api怎么不用grape挂在rails上

@kingwkb 这是另一个问题了, 主要现在还很小, 直接 Rails 我觉得蛮好, 也没到要换个框架性能才能撑的阶段。

第二, Grape, 也要用这些办法来 render json 的吧, 难道 Grape 有啥别的魔法 ?

#18楼 @larryzhao Grape有 Entity

再小把api分离出来都有有必要的,增加不了几很代码,但整个结构变的清晰不少,又不是要增加很多代码

@kingwkb 我去看看这个Entity. 我觉得 Rails 里面加个 namespace 结构也挺清晰的啊, 大家觉得呢

@kingwkb 简单看了一下, 用 Entity 应该会更清楚些, 不过空欢喜了一下, 我本来以为是个 Render json 的

#16楼 @Saito 其实dsl语法差不多

  • json.array! vs collection
  • json.set! vs node
  • json.extract! vs attributes
# app/views/users/show.rabl
object @user

# Declare the properties to include
attributes :first_name, :last_name

# Alias 'age' to 'years_old'
attributes :age => :years_old

# Include a custom node with full_name for user
node :full_name do |user|
  [user.first_name, user.last_name].join(" ")
end

# Include a custom node related to if the user can drink
node :can_drink do |user|
  user.age >= 21
end

#22楼 @hooopo 好吧, 我说实话. 我用 jbuilder 还有另外一个原因是我贡献了一行代码...并且为此我看了它的代码, 比较了解.

Serializer 真是瞎, 不能用 helper method..

之前用过RABL,然后因为rail4对jbuilder的支持,就用jbuilder了。暂时还没感觉到太大差异,习惯就好

#7楼 @larryzhao 我的意思是,比如index页只需要显示很少几个属性,show页要显示大部分属性,这时,都用同一个serializer,对index页来说,多处理了很多不必要的数据。除非你的API总是返回全部属性,不然,如果针对请求返回不同的数据的话,就要设计很多serializer,而这些serializer又都在同一个文件夹下。

个人比较偏向 active_model_serializers,专门抽象出一层,用面向对象的方式写,测试起来也方便

#26楼 @yanhao 是的, 就要设计多个serializer

jbuilder +1

把 render 的数据变大, 类型变丰富又简单测了一下, 数据更新在主贴了, 基本准备用 jbuilder 了

jbuilder + 1

以前用过acts_as_api在一个小项目上,貌似这个不更新了。

公司老项目用的是 Hash#to_json,用得我想哭了,不过自从我全权接手后,直接把几个重要的 API 用 Jbuilder 重写了,速度快了整整一倍!

喜欢 rabl 预设做出来跟 xml 一样可自我辨识 (self-describing) 的 node,这样子 api 增加东西可以与先前相容。而 rabl 的无脑暴力所有东西都给他 cache 目前用来也很爽。 Rabl 的缺陷是 DSL 有点难懂,而且用了一些魔法,有时候以为能插用 plain ruby 时反而不行

object @foo
puts @foo
do_something @foo.bar

上次试,第二行第三行都会出错误。

#33楼 @lulalala 其实rabl的cache设计的有些问题,看issue里是要1.0会重新设计语法和cache,不过作者好像很忙的样子。。

#34楼 @hooopo 结果刚刚就踩 rabl 的雷了,两个 view template 用同一个 model object ,会用同一个 key。Rabl 自动生成的 key 竟然不包括 view name/path。

用grape的话,推荐直接用grape-entity做json输出,即方便可以重用又不失灵活性

#36楼 @rainchen 这位哥们说的好,赞一个。

#8楼 @Rei 我用 Jbuilder 1.5.2 grape 0.6.1 返回输出都是string 但是用 Jbuilder 1.5.2 grape 0.3.2 返回输入json 正确 不知道这里有什么坑吗?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册