Rails 用啥来 render json ?

larryzhao · July 30, 2013 · Last by what_is_ruby replied at October 29, 2013 · 9248 hits
Topic has been selected as the excellent topic by the admin.

最近在搭一些 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 正确 不知道这里有什么坑吗?

You need to Sign in before reply, if you don't have an account, please Sign up first.