Rails中to_json的默认值为:include

让我们说我有一个属于用户的模型Post。 要转换为json,我会做这样的事情

@reply.to_json(:include => {:user => {:only => [:email, :id]}, :only => [:title, :id]) 

但是,我想为此设置一些默认值,所以我不必每次都指定: 我试图覆盖as_json来实现这一目标。 当我在User模型中添加as_json时,在我执行@ user.to_json时调用它,但是当用户包含在@ reply.to_json中时,忽略了用户的重写as_json。

我该如何工作?

谢谢

您可以通过覆盖模型中的serializable_hash来实现此目的,如下所示:

 class Reply < ActiveRecord::Base def serializable_hash(options={}) options = { :include => {:user => {:only => [:email, :id]}, :only => [:title, :id] }.update(options) super(options) end end 

这将影响所有可序列化的方法,包括serializable_hashto_jsonto_xml

在回复模型中:

 def as_json(options = {}) super options.merge(:methods => [:user], :only => [:id, :title]) end 

在用户模型中:

 def as_json(options = {}) super options.merge(:only => [:id, :email]) end 

当关联作为方法而不是include包含时,它将在其上运行.to_json。

您可以向ActiveRecord :: Base添加另一个方法,例如self.to_minimal_json(* only_fields)并在那里构建您的.to_json调用。

不引人注目,但可能会奏效。

所以我发现问题是对于包含,而不是调用as_json来生成json,Rails直接调用serializable_hash。 猴子修补修复了这个问题。 把它放在初始化器中

 module ActiveRecord #:nodoc: module Serialization def serializable_hash(options = nil) options = options.try(:clone) || {} options[:except] = Array.wrap(options[:except]).map { |n| n.to_s } options[:except] |= Array.wrap(self.class.inheritance_column) hash = super(options) #serializable_add_includes(options) do |association, records, opts| #hash[association] = records.is_a?(Enumerable) ? #records.map { |r| r.serializable_hash(opts) } : #records.serializable_hash(opts) #end serializable_add_includes(options) do |association, records, opts| hash[association] = records.is_a?(Enumerable) ? records.map { |r| r.as_json(opts.merge(:no_root => true)) } : records.as_json(opts.merge(:no_root => true)) end hash end end end module ActiveModel # == Active Model JSON Serializer module Serializers module JSON def as_json(options = nil) hash = serializable_hash(options) if include_root_in_json and !options[:no_root] custom_root = options && options[:root] hash = { custom_root || self.class.model_name.element => hash } end hash end end end end 

注意serializable_hash调用是如何用as_json替换的(带有一个额外的参数来阻止在include中添加root)。 现在,如果你的模型中有as_json,即使是include,也会调用它

由于选项在某些情况下可能为零,我们最好注意一下:

 module ActiveModel # == Active Model JSON Serializer module Serializers module JSON def as_json(options) options ||= {} hash = serializable_hash(options) if include_root_in_json and !options[:no_root] custom_root = options && options[:root] hash = { custom_root || self.class.model_name.element => hash } end hash end end end end