在上一篇文章Rails3中的JSON知道render :json => @xxx
其实是调用的to_json
方法,而to_json
其实是ActiveSupport::JSON.encode
方法。
在数据量比较小的时候,性能还可以,但是当数据量很大的时候,性能非常差,这里我们可以用一些第三方的快的json库来解析:
我使用的是oj,配合MultiJson(Rails3中已经有了,但是只在decode的时候有用到)
# Gemfile
gem
'oj'
# application.rb
MultiJson.
engine =
:oj
render
:json
=> MultiJson.
encode
(api_response
)
其他一些json库
supported-json-engines
Rails 3.2.12
to_json
#to_json
是由gem ‘json’引入的,但是ActiveSupport重写了,和as_json
联系起来
[
Object,
Array,
FalseClass,
Float,
Hash,
Integer,
NilClass,
String,
TrueClass
].
each
do
|klass
|
klass.
class_eval
do
def to_json
(options =
nil
)
ActiveSupport::JSON.
encode
(
self, options
)
end
end
end
ActiveSupport::JSON#encode
def encode
(value, use_options =
true
)
check_for_circular_references
(value
)
do
jsonified = use_options ? value.
as_json
(options_for
(value
)
) : value.
as_json
jsonified.
encode_json
(
self
)
end
end
#as_json
这个直接看api就知道了,http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html
render :json => @xxx
来看看render :json是如何实现的:
actionpack/lib/action_controller/metal/renderers
add
:json
do
|json, options
|
json = json.
to_json
(options
)
unless json.
kind_of?
(
String
)
json =
"#{options[:callback]}(#{json})"
unless options
[
:callback
].
blank?
self.
content_type
||=
Mime::JSON
json
end
可以看到就是调用了to_json
,如果是String就直接返回,如果有callback就返回jsonp的格式
另外我们可以添加新的`renderer`:
ActionController::Renderers.
add
:csv
do
|obj, options
|
filename = options
[
:filename
]
||
'data'
str = obj.
respond_to?
(
:to_csv
) ? obj.
to_csv : obj.
to_s
send_data str,
:type
=>
Mime::CSV,
:disposition
=>
"attachment; filename=#{filename}.csv"
end
# 使用
render
:csv
=>
@csvable,
:filename
=>
@csvable.
name
总结:尽量不要在rails3中重写to_json,如果确实需要自己构造json,重写as_json方法。