Mongoid - 在 JSON API 响应中序列化 DateTime 字段时获取日期而不是时间

Mongoid - Getting Date instead of Time when serializing DateTime field in JSON API response

我正在编写一个 Rails 应用程序作为仅针对移动应用程序的 Web 服务。我使用 --api--skip-active-record 开关创建了它。我的模型有一个 DateTime 字段。

这是我的模型代码和我在控制器中调用的方法。因为我用的是--api,所以没有查看代码:

class GroceryItem
  include Mongoid::Document
  field :name, type: String
  field :expiry, type: Date
end

# grocery_items_controller.rb
# GET /grocery_items/1
def show
  render json: @grocery_item
end

在数据库中,我可以看到正在存储该字段的时间部分:

db.grocery_items.find()
{ "_id" : ObjectId("58a9298da1c1d12e7cee02d9"), "name" : "Chocolate", "expiry" : ISODate("2017-02-19T05:13:49.253Z") }

我也可以在 Rails 控制台中看到:

irb(main):003:0> GroceryItem.first
=> #<GroceryItem _id: 58a9298da1c1d12e7cee02d9, name: "Chocolate", expiry: 2017-02-19 05:13:49 UTC>

但是,当我尝试使用我的 GroceryItem 模型 class 上的方法访问过期时间时,我得到了一个 Date 对象。我只得到数据的日期部分,没有时间部分:

irb(main):004:0> GroceryItem.first.expiry
=> Sun, 19 Feb 2017

irb(main):005:0> GroceryItem.first.expiry.class
=> Date

irb(main):006:0> GroceryItem.first.expiry.to_s
=> "2017-02-19"

在实例上调用 to_jsonas_json 也会省略数据:

irb(main):008:0> GroceryItem.first.to_json
=> "{\"_id\":{\"$oid\":\"58a9298da1c1d12e7cee02d9\"},\"expiry\":\"2017-02-19\",\"name\":\"Chocolate\"}"

irb(main):009:0> GroceryItem.first.as_json
=> {"_id"=>BSON::ObjectId('58a9298da1c1d12e7cee02d9'), "expiry"=>Sun, 19 Feb 2017, "name"=>"Chocolate"}

这导致我的 JSON 响应省略了数据。我假设控制器中的渲染过程使用 to_jsonas_json 进行渲染:

{
    "_id": {
        "$oid": "58a9298da1c1d12e7cee02d9"
    },
    "expiry": "2017-02-19",
    "name": "Chocolate"
}

我终于能够通过调用以下命令弄清楚如何访问这些数据。你可以看到我是如何最终得到时间的 Ruby class:

irb(main):010:0> GroceryItem.first.attributes[:expiry]
=> 2017-02-19 05:13:49 UTC

irb(main):011:0> GroceryItem.first.attributes[:expiry].class
=> Time

这让我终于有了一种以与 ISO8601 规范兼容的方式序列化数据的方法,以匹配存储在 MongoDB:

中的数据
irb(main):012:0> GroceryItem.first.attributes[:expiry].utc.iso8601
=> "2017-02-19T05:13:49Z"

当然,这种行为是不正确的。当开发人员为字段选择 DataTime 类型时,他们必须希望时间组件通过。否则,他们会改用 Date 类型。我现在明白我可以通过创建一个视图以我认为合适的方式呈现 JSON 来覆盖默认的 Rails API 和 Mongoid 配对行为,但我正在考虑提交错误报告因为我觉得默认行为应该更改为在开发人员选择 DateTime 字段类型时自动呈现存储在数据库中的所有数据。

我想知道在我继续提交错误报告之前这里是否有人对此问题有任何意见。

问题似乎出在您的代码中:

class GroceryItem
  include Mongoid::Document
  field :name, type: String
  field :expiry, type: Date
end

这里,expiry 的类型是 Date,所以它应该是 return 没有时间成分的 Date。我认为使用合适的类型可以解决您的问题。