将虚拟属性添加到json输出

Lin*_*nus 61 json ruby-on-rails

假设我有一个处理TODO列表的应用程序.该清单已完成和未完成的项目.现在我想向列表对象添加两个虚拟属性; 列表中已完成和未完成的项目数.我还需要在json输出中显示这些.

我的模型中有两个方法可以获取未完成/已完成的项目:

def unfinished_items 
  self.items.where("status = ?", false) 
end 

def finished_items 
  self.items.where("status = ?", true) 
end
Run Code Online (Sandbox Code Playgroud)

那么,我怎样才能在json输出中得到这两个方法的计数?

我正在使用Rails 3.1

mu *_*ort 112

Rails中对象的序列化有两个步骤:

  • 首先,as_json调用将对象转换为简化的Hash.
  • 然后,to_jsonas_json返回值上调用以获取最终的JSON字符串.

您通常希望to_json独自留下所以您需要做的就是添加您自己的as_json实现类似:

def as_json(options = { })
  # just in case someone says as_json(nil) and bypasses
  # our default...
  super((options || { }).merge({
    :methods => [:finished_items, :unfinished_items]
  }))
end
Run Code Online (Sandbox Code Playgroud)

你也可以这样做:

def as_json(options = { })
  h = super(options)
  h[:finished]   = finished_items
  h[:unfinished] = unfinished_items
  h
end
Run Code Online (Sandbox Code Playgroud)

如果要为方法支持的值使用不同的名称.

如果您关心XML和JSON,请查看serializable_hash.

  • 我得到了这个错误的顶部:nil的未定义方法`merge':NilClass所以我用'(options || {})替换`options.merge`.合并. (3认同)

Asw*_*nan 29

使用Rails 4,您可以执行以下操作 -

render json: @my_object.to_json(:methods => [:finished_items, :unfinished_items])
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助那些处于后期/最新版本的人


ran*_*mor 17

另一种方法是将其添加到您的模型中:

def attributes
  super.merge({'unfinished' => unfinished_items, 'finished' => finished_items})
end
Run Code Online (Sandbox Code Playgroud)

这也可以自动用于xml序列化. http://api.rubyonrails.org/classes/ActiveModel/Serialization.html 请注意,您可能希望使用字符串作为键,因为在对rails 3中的键进行排序时,该方法无法处理符号.但它不是在rails 4中排序,所以不应该有问题了.