蒸汽通过日期参数
Vapor pass date parameter
在我的 Vapor 3 应用程序中,我有一个 Event
模型,它具有 startDate: Date
和 endDate: Date
.
属性
现在,我想知道如何在 POST 请求中传递这些日期值。在 Postman 中,我在 x-www-form-urlencoded
中尝试了以下操作:
startDate -> 2019-03-14
这returns下面的错误:
Could not convert to Double
: str(\"2019-03-14\")
显然,Date
变成了 Double
。
那么,相反,我需要传递什么值?
备注
我知道,在 Postman 中,我可以插入 {{$timestamp}}
,但是 1) 在 Postman 外部使用 API 时,这不能回答我的问题;2) 这不允许我要输入 现在 .
以外的日期
我不确定 x-www-form-urlencoded
,因为我测试了它,如果我发送一个 0
的日期,它会将它解码为 2001-01-01 00:00:00 +0000
,我认为它肯定应该是 1970-01-01 00:00:00 +0000
.
但是使用 JSON 有效载荷,您可以灵活地提供一个 JSONDecoder
根据需要配置的。
struct Payload: Content {
var date: Date
}
如果您想将日期作为 UNIX 时间戳发送
router.post("check") { req throws -> Future<String> in
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970 // choose it for unix-timestamp
return try req.content.decode(json: Payload.self, using: decoder).map { p in
return String(describing: p.date)
}
}
如果您想以自己的格式发送日期
router.post("check") { req throws -> Future<String> in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.timeZone = TimeZone(secondsFromGMT: 0)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter) // custom date formatter
return try req.content.decode(json: Payload.self, using: decoder).map { p in
return String(describing: p.date)
}
}
因此,对于 unix-timestamp,您应该发送从 1970 年开始的秒数,例如0
将被解码为 1970-01-01 00:00:00 +0000
.
对于上述自定义格式,您应该发送 2018-01-01 00:00:00
之类的日期以将其解码为 2018-01-01 00:00:00 +0000
UPD:你可以写一个扩展来漂亮地解码它
extension ContentContainer where M: Request {
func decodeJson<D>(_ payload: D.Type) throws -> Future<D> where D: Decodable {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.timeZone = TimeZone(secondsFromGMT: 0)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)
return try decode(json: payload, using: decoder)
}
}
这样你就可以像这样解码你的有效载荷
router.post("check") { (req) throws -> Future<String> in
return try req.content.decodeJson(Payload.self).map { p in
return String(describing: p.date)
}
}
所以这里的问题是,默认情况下,Date
实例使用自 2001 年 1 月 1 日以来的时间间隔进行解码。Vapor 使用的 URL form decoder 不支持不同的日期策略,例如JSONDecoder
目前确实如此,因此您必须以不同的方式进行解码。以下是我可以提出的一些想法:
- 只需在请求中发送时间戳即可。为了在 Postman 中测试不同的日期,您可以在预请求脚本中设置环境变量并在请求正文中访问它。
手动实现 Event.init(from:)
和 .encode(to:)
方法。只是为了确保您不会破坏 Fluent 编码,您可能需要添加一些额外的逻辑,但它应该可以工作。这是一个例子:
final class Event: Model {
static let formDateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
var startDate: Date
var endDate: Date
init(from decoder: Decoder)throws {
let container = try decoder.container(keyedby: CodingKeys.self)
if let start = try? container.decode(String.self, keyedBy: .startDate), let date = Event.formDateFormatter.string(from: start) {
self.startDate = date
} else {
self.startDate = try container.decode(Date.self, keyedBy: .startDate)
}
if let end = try? container.decode(String.self, keyedBy: .endDate), let date = Event.formDateFormatter.string(from: end) {
self.endDate = date
} else {
self.endDate = try container.decode(Date.self, keyedBy: .endDate)
}
}
}
我意识到 Date
对象在查询时以以下格式返回:
2021-12-31T14:29:00Z
所以这就是我试图通过的方法并且有效!无需任何自定义解码。
在我的 Vapor 3 应用程序中,我有一个 Event
模型,它具有 startDate: Date
和 endDate: Date
.
属性
现在,我想知道如何在 POST 请求中传递这些日期值。在 Postman 中,我在 x-www-form-urlencoded
中尝试了以下操作:
startDate -> 2019-03-14
这returns下面的错误:
Could not convert to
Double
: str(\"2019-03-14\")
显然,Date
变成了 Double
。
那么,相反,我需要传递什么值?
备注
我知道,在 Postman 中,我可以插入 {{$timestamp}}
,但是 1) 在 Postman 外部使用 API 时,这不能回答我的问题;2) 这不允许我要输入 现在 .
我不确定 x-www-form-urlencoded
,因为我测试了它,如果我发送一个 0
的日期,它会将它解码为 2001-01-01 00:00:00 +0000
,我认为它肯定应该是 1970-01-01 00:00:00 +0000
.
但是使用 JSON 有效载荷,您可以灵活地提供一个 JSONDecoder
根据需要配置的。
struct Payload: Content {
var date: Date
}
如果您想将日期作为 UNIX 时间戳发送
router.post("check") { req throws -> Future<String> in
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970 // choose it for unix-timestamp
return try req.content.decode(json: Payload.self, using: decoder).map { p in
return String(describing: p.date)
}
}
如果您想以自己的格式发送日期
router.post("check") { req throws -> Future<String> in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.timeZone = TimeZone(secondsFromGMT: 0)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter) // custom date formatter
return try req.content.decode(json: Payload.self, using: decoder).map { p in
return String(describing: p.date)
}
}
因此,对于 unix-timestamp,您应该发送从 1970 年开始的秒数,例如0
将被解码为 1970-01-01 00:00:00 +0000
.
对于上述自定义格式,您应该发送 2018-01-01 00:00:00
之类的日期以将其解码为 2018-01-01 00:00:00 +0000
UPD:你可以写一个扩展来漂亮地解码它
extension ContentContainer where M: Request {
func decodeJson<D>(_ payload: D.Type) throws -> Future<D> where D: Decodable {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.timeZone = TimeZone(secondsFromGMT: 0)
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)
return try decode(json: payload, using: decoder)
}
}
这样你就可以像这样解码你的有效载荷
router.post("check") { (req) throws -> Future<String> in
return try req.content.decodeJson(Payload.self).map { p in
return String(describing: p.date)
}
}
所以这里的问题是,默认情况下,Date
实例使用自 2001 年 1 月 1 日以来的时间间隔进行解码。Vapor 使用的 URL form decoder 不支持不同的日期策略,例如JSONDecoder
目前确实如此,因此您必须以不同的方式进行解码。以下是我可以提出的一些想法:
- 只需在请求中发送时间戳即可。为了在 Postman 中测试不同的日期,您可以在预请求脚本中设置环境变量并在请求正文中访问它。
手动实现
Event.init(from:)
和.encode(to:)
方法。只是为了确保您不会破坏 Fluent 编码,您可能需要添加一些额外的逻辑,但它应该可以工作。这是一个例子:final class Event: Model { static let formDateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.calendar = Calendar(identifier: .iso8601) formatter.locale = Locale(identifier: "en_US_POSIX") formatter.timeZone = TimeZone(secondsFromGMT: 0) formatter.dateFormat = "yyyy-MM-dd" return formatter }() var startDate: Date var endDate: Date init(from decoder: Decoder)throws { let container = try decoder.container(keyedby: CodingKeys.self) if let start = try? container.decode(String.self, keyedBy: .startDate), let date = Event.formDateFormatter.string(from: start) { self.startDate = date } else { self.startDate = try container.decode(Date.self, keyedBy: .startDate) } if let end = try? container.decode(String.self, keyedBy: .endDate), let date = Event.formDateFormatter.string(from: end) { self.endDate = date } else { self.endDate = try container.decode(Date.self, keyedBy: .endDate) } } }
我意识到 Date
对象在查询时以以下格式返回:
2021-12-31T14:29:00Z
所以这就是我试图通过的方法并且有效!无需任何自定义解码。