0

给定带有日期时间和要在图表中显示的数据的文档,如何在不从 BSON 转换为 Ruby 再最终转换为 JSON 的情况下直接返回查询结果?

问题:时间值在 BSON 中为客户端正确存储,但是涉及 Ruby 会将其转换为时间对象,我必须这样做time.to_i * 1000才能正确存储在返回的 JSON 中。无论如何,我不需要转换任何数据,所以这只是一种浪费。

我在 Heroku + MongoHQ 上运行 Rails,Mongoid。我想让 Rails 应用程序对查询进行授权,但不将响应转换为 Ruby 对象。

def show_graph
  raw_bson = TheModel.all_raw_documents_matching(query_params)
  raw_bson.to_json  
  # Alternatively, this BSON to JSON could be happening client side. 
  # side. Whatever, just don't convert to ruby objects...
end
4

1 回答 1

0

你的问题有很多观点。而不是 BSON 反序列化,我看到该to_json方法如何处理ruby​​ 对象的序列Date化更为关键。Time

我想到的最简单,最棘手的方法是覆盖类的as_json方法Time

class Time
 def as_json(options={})
    self.to_i * 1000
 end
end

hash = {:time => Time.now}
hash.to_json # "{\"a\":1367329412000}" 

您可以将其放入初始化程序中。这是一个非常简单的解决方案,但您必须记住,Time您的应用程序中的每个 ruby​​ 对象都将使用您的自定义方法进行序列化。这可能很好,也可能不好,真的很难说,一些宝石可能依赖于此,或不依赖于此。

一种更安全的方法是编写一个包装器并调用它而不是to_json

def to_json_with_time
  converted_hash = self.attributes.map{|k,v| {k => v.to_i * 1000 if v.is_a?(Time)} }.reduce(:merge)
  converted_hash.to_json
end

最后,如果你真的想重写 Mongoid 序列化和反序列化对象的方式,并且如果你想跳过 BSON 过程,你必须定义mongoizedemongoize方法。在这里您可以找到文档:自定义字段序列化

**更新**

问题是序列化而不是反序列化。如果你从查询中得到一个原始 BSON,你仍然有一个Timeruby​​ 对象的字符串表示。您不能将 BSON 直接转换为 JSON,因为如果不从 rubyTime​​ 类传递,就无法将时间的字符串表示形式转换为整数表示形式。

这是一个如何使用 Mongoid 自定义字段序列化的示例。

class Foo
  include Mongoid::Document

  field :bar, type: Time
end


class Time

  # The instance method mongoize take an instance of your object, and converts it into how it will be stored in the database
  def mongoize
    self.to_i * 1000
  end

  # The class method mongoize takes an object that you would use to set on your model from your application code, and create the object as it would be stored in the database
  def self.mongoize(o)
    o.mongoize
  end

  # The class method demongoize takes an object as how it was stored in the database, and is responsible for instantiating an object of your custom type.
  def self.demongoize(object)
    object
  end

end

Foo.create(:bar => Time.now) #<Foo _id: 518295cebb9ab4e1d2000006, _type: nil, bar: 1367512526> 
Foo.last.as_json # {"_id"=>"518295cebb9ab4e1d2000006", "bar"=>1367512526} 
于 2013-04-30T14:11:12.857 回答