繁体   English   中英

如何在Rails中覆盖to_json?

[英]How to override to_json in Rails?


更新:

这个问题没有得到适当的探索。 真正的问题在于render :json

原始问题中的第一个代码粘贴将产生预期结果。 但是,仍然有一个警告。 看这个例子:

render :json => current_user

一样的

render :json => current_user.to_json

也就是说, render :json不会自动调用与User对象关联的to_json方法。 实际上 ,如果在User模型上覆盖to_json ,则render :json => @user将生成下面描述的ArgumentError

摘要

# works if User#to_json is not overridden
render :json => current_user

# If User#to_json is overridden, User requires explicit call
render :json => current_user.to_json

这一切对我来说都很愚蠢。 这似乎告诉我,当type :json被指定时, render实际上并没有调用Model#to_json 谁能解释一下这里到底发生了什么?

任何可以帮助我的genii都可能回答我的另一个问题: 如何通过在Rails中组合@ foo.to_json(options)和@ bars.to_json(options)来构建JSON响应


原始问题:

我在SO上看过其他一些例子,但我没有做我正在寻找的事情。

我尝试着:

class User < ActiveRecord::Base

  # this actually works! (see update summary above)
  def to_json
    super(:only => :username, :methods => [:foo, :bar])
  end

end

我收到了ArgumentError: wrong number of arguments (1 for 0)

/usr/lib/ruby/gems/1.9.1/gems/activesupport-2.3.5/lib/active_support/json/encoders/object.rb:4:in `to_json

有任何想法吗?

你得到的是ArgumentError: wrong number of arguments (1 for 0)因为to_json需要用一个参数覆盖,即options哈希。

def to_json(options)
  ...
end

to_jsonas_json和渲染的更长解释:

在ActiveSupport 2.3.3中,添加了as_json来解决您遇到的问题。 json的创建应该与json的渲染分开。

现在,任何时候to_json被称为一个对象上, as_json被调用以创建数据结构,然后该散列被编码为使用JSON字符串ActiveSupport::json.encode 所有类型都会发生这种情况:对象,数字,日期,字符串等(请参阅ActiveSupport代码)。

ActiveRecord对象的行为方式相同。 有一个默认的as_json实现,它创建一个包含所有模型属性的哈希。 您应该在模型中覆盖as_json以创建所需的JSON结构 as_json ,就像旧的to_json ,采用一个选项哈希,你可以指定属性和方法以声明方式包含。

def as_json(options)
  # this example ignores the user's options
  super(:only => [:email, :handle])
end

在你的控制器中, render :json => o可以接受一个字符串或一个对象。 如果它是一个字符串,它是穿过作为响应体中,如果它是一个对象, to_json被调用时,其触发as_json如上所述。

因此,只要您的模型使用as_json覆盖(或不覆盖)正确表示,显示一个模型的控制器代码应如下所示:

format.json { render :json => @user }

故事的寓意是: 避免直接调用to_json ,允许render为你做。 如果需要调整JSON输出,请调用as_json

format.json { render :json => 
    @user.as_json(:only => [:username], :methods => [:avatar]) }

如果您在Rails 3中遇到此问题,请覆盖serializable_hash而不是as_json 这将免费获得您的XML格式:)

这让我永远想通了。 希望能帮助别人。

对于那些不想忽略用户选项而又添加他们的选项的人:

def as_json(options)
  # this example DOES NOT ignore the user's options
  super({:only => [:email, :handle]}.merge(options))
end

希望这有助于任何人:)

覆盖不是to_json,而是as_json。 从as_json打电话给你想要的:

试试这个:

def as_json 
 { :username => username, :foo => foo, :bar => bar }
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM