如果文档中包含日期时间和要在图形中显示的数据,如何直接返回查询结果而不从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
答案 0 :(得分:0)
你的问题有很多观点。
我认为to_json
方法处理Date
和Time
ruby对象的序列化更为关键,而不是BSON反序列化。
我想到的最简单,最棘手的方法是覆盖as_json
类的Time
方法:
class Time
def as_json(options={})
self.to_i * 1000
end
end
hash = {:time => Time.now}
hash.to_json # "{\"a\":1367329412000}"
您可以将其放入初始化程序中。这是一个非常简单的解决方案,但您必须记住,您的应用中的每个ruby Time
对象都将使用您的自定义方法进行序列化。这可能没问题,或者不是,它确实是很难说,有些宝石可能依赖于此,或不是。
更安全的方法是编写一个包装器并调用它而不是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过程,你必须定义mongoize
和demongoize
方法。
您可以在此处找到文档:Custom Field Serialization
问题是序列化而不是反序列化。如果从查询中获得原始BSON,则仍然具有Time
ruby对象的字符串表示形式。
您不能将BSON直接转换为JSON,因为无法将时间的字符串表示转换为整数表示而不从ruby Time
类转换。
这是一个如何使用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}