我有一个数据模型,看起来像这样。
struct Post: Content, MySQLModel, Migration, Equatable {
var id: Int?
var userId: Int
var title: String
var body: String
var creationDate: Date?
var lastEditDate: Date?
static func prepare(on connection: MySQLConnection) -> Future<Void> {
return MySQLDatabase.create(self, on: connection) { builder in
builder.field(for: \.id, isIdentifier: true)
builder.field(for: \.userId)
builder.field(for: \.title)
builder.field(for: \.body, type: .text())
builder.field(for: \.creationDate)
builder.field(for: \.lastEditDate)
}
}
}
如果我在数据库里有一些实例 我可以安全地进行一个查询 在路径中传递帖子的id 然后我就会得到一个对象 以字符串的格式写上创建到最后编辑的日期
func retrievePost(on req: Request) throws -> Future<Post> {
let id = try req.parameters.next(Int.self)
return Post.find(id, on: req).map(to: Post.self) { post in
guard let post = post else {
throw Abort(.notFound)
}
return post
}
}
如果我做一个GET查询,这就是我在响应体中得到的结果。
{
"body": "value",
"id": 8723,
"title": "value",
"creationDate": "2020-05-27T15:24:41Z",
"userId": 0
}
这就是我的PUT方法的实现
func updatePost(on req: Request) throws -> Future<Post> {
var updatedPost = try req.content.syncDecode(Post.self)
guard let id = updatedPost.id else {
throw Abort(.badRequest)
}
return Post.find(id, on: req).flatMap { post in
guard let _ = post else {
throw Abort(.notFound)
}
return updatedPost.save(on: req)
}
}
但如果我发送一个PUT请求,传递与GET响应体中相同的字段,创建日期格式为字符串,我就会得到这个错误。
{
"error": true,
"reason": "Could not convert to `Double`: str(\"2020-05-27T15:24:41Z\")"
}
它期望的是一个双数 如果我尝试发送1970年之后的秒数,它就能正常工作,但我不明白为什么同一个日期对象使用字符串日期编码,而使用双数解码。如何绕过这个问题?
和你一模一样,我也是这么用的。
struct MyForm {
let myDate:Date
}
在 .leaf
表单中,我使用了不同的字段名来允许用户修改日期。
<input type="date" name="userDate" value="#date(myDate, "yyyy-MM-dd")">
然后,在提交按钮的 onclick
事件,我使用javascript计算日期的时间戳值,并将其返回到 "原始 "字段。
var d = new Date(f["userDate"].value);
f['myDate'].value = d.getTime()/1000;
return true;
这个 decode
现在应该可以正常工作了。
我还使用了一个customTag来表示较短格式的日期。
struct DateTag:LeafTag
{
public func render(_ context:LeafContext) throws -> LeafData
{
try context.requireParameterCount(2)
guard let timestamp = context.parameters.first?.double else { return .string("") }
guard let format = context.parameters[1].string else { throw "DateTag needs a format to work on" }
let df = DateFormatter()
df.dateFormat = format
return .string(df.string(from:Date(timeIntervalSince1970:timestamp)))
}
}
嵌套的双引号是没有问题的 因为Leaf只对内层的设置进行处理, 而外层的设置则留给了浏览器.