Rails 用啥来 render json ?

larryzhao · 2013年07月30日 · 最后由 what_is_ruby 回复于 2013年10月29日 · 9242 次阅读
本帖已被管理员设置为精华贴

最近在搭一些 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 对我现在来说很不方便。

看 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 正确 不知道这里有什么坑吗?

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