Ruby on Rails高级JSON序列化

我想在我的rails应用程序中通过JSON呈现所有文章的索引以及完整的文章,但是我在弄清楚如何做到这一点时遇到了一些麻烦。

这是我的控制器:

if params[:id] @article = Article.find(params[:id]) else @article = Article.published.not_draft.by_recent.first end respond_to do |format| format.js { render :json => @article.to_json( :except => [ :created_at, :updated_at, :draft, :id, :publish ], :include => { :comments => { :only => [:body] } }), :callback => params[:callback]} end 

我想在响应中做的是添加所有文章的索引,如下所示:

 @index = Article.find(:all, :select => 'id, title') 

我能够做到的唯一方法是将索引和文章放入哈希或数组中,然后将其放入JSON中。

 @response = { :item => @article, :index => @index } 

两个完整代码:

 @index = Article.find(:all, :select => 'id, title') if params[:id] @article = Article.find(params[:id]) else @article = Article.published.not_draft.by_recent.first end @response = { :item => @article, :index => @index } respond_to do |format| format.js { render :json => @response.to_json(), :callback => params[:callback]} end 

这样就好了,除了现在我不能指定:include:except并让它正确渲染。

您在提问中提示解决方案。 您最有可能想要构建一个哈希来呈现给JSON。 现在这样做的首选方法是为as_json方法提供一个实现。 as_json提供了一种通过构建包含要编码的数据的哈希来自定义to_json输出的正式方法。

有关as_json和to_json如何交互的更全面的处理可以在Jonathan Julian的博客上找到。

为了清楚起见,上面的代码适用于:include和:except。 通过工作我的意思是它不会引发错误。 问题是它包含对索引中每篇文章的评论。 我只想包含:item的注释,而不是索引中列出的任何文章。

我无法将嵌套作为哈希或OpenStruct对象工作。

嵌套:include抛出错误,嵌套在:除了不抛出错误,但没有任何过滤掉,:created_at等仍然出现。

 ... @response = { :item => @article, :index => @index } format.js { render :json => @response.to_json( :except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}, :include => { :item => { :comments => { :only => [:body] } }}), :callback => params[:callback]} end 

您应该能够嵌套:include:except等,如下所示:

 :except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}... 

如果这不起作用,请将其设为对象(例如OpenStruct)而不是哈希。

– 马库斯

to_json有一个:method选项,包含您命名的任何方法的结果,您可以在该模型上定义一个方法,该方法返回您在JSON中需要的其他数据。

(请接受回答)

我认为nirvdrum提供的链接可以解答你的问题。 我只回答,因为没有人提到过encode_json

在你的情况下,你应该只处理as_json 。 通过构建一个哈希(对as_json进行各种调用)并将其发送到render :json => ... (不调用to_json )或者只是在模型上实现as_json并让rails完成所有工作。 (但我怀疑你需要前者。)

如果你真的需要在渲染的响应中使用一些花哨的js,那么你可以在类中实现encode_json (同样,不是to_json )。 例如:

 class JsEmptyClosure def encode_json(*args) "jQuery[\"noop\"] || function(){}" end def as_json(*args) self end end 

现在,这将使用有效的js响应to_json (但请注意它实际上不是json)。

谢谢你的问题,我能够为具有多个关联的模型自定义我的json格式。

渲染json:@ posts.to_json(

:except => [:created_at,:updated_at,:user_id],

:include => {

:user => {:only => [:email,:phone]},

:location => {:only => [:title,:lat,:lon,:street,:city,:state,:zipcode]},

:uploads => {:only => [:image]}

}

我建议重载属性方法以返回将在to_json输出中自动使用的alternat哈希。

 class Article def attributes { ... } # define your hash that you want to return at the '...' end end 

对我来说,这似乎比直接使用to_json更简单。