Ruby on Rails高级JSON序列化

时间:2009-03-03 19:52:48

标签: ruby-on-rails ruby json serialization xml-serialization

我希望在我的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并让它正确呈现。

7 个答案:

答案 0 :(得分:28)

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

可以在Jonathan Julian's weblog上找到有关as_json和to_json如何互动的更全面的处理方法。

答案 1 :(得分:2)

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

我无法将嵌套作为哈希或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

答案 2 :(得分:1)

你应该能够像{I}}那样嵌套:include:except等:

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

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

- 马库斯

答案 3 :(得分:1)

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

答案 4 :(得分:1)

(请接受回答)

我认为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)。

答案 5 :(得分:0)

感谢您提出的问题,我可以为具有多个关联的模型自定义我的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,   :邮政编码]},

     

:uploads => {:only => [:图像]}

     

}
  )

答案 6 :(得分:0)

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

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

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