Vapor.Date对象是以字符串格式解码的,但解码器期望的是一个双数。但解码器期望的是一个双倍值

问题描述 投票:2回答:1

我有一个数据模型,看起来像这样。

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年之后的秒数,它就能正常工作,但我不明白为什么同一个日期对象使用字符串日期编码,而使用双数解码。如何绕过这个问题?

swift vapor
1个回答
1
投票

和你一模一样,我也是这么用的。

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只对内层的设置进行处理, 而外层的设置则留给了浏览器.

© www.soinside.com 2019 - 2024. All rights reserved.