I have a data model that looks like this:
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)
}
}
}
And if I have some instances in the database, I can safely make a query passing the id of the post in the path, and I would get an object with a creation/last edit date formatted in a string format:
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
}
}
If I make a GET query, this is what I get back in the response body:
{
"body": "value",
"id": 8723,
"title": "value",
"creationDate": "2020-05-27T15:24:41Z",
"userId": 0
}
And this is my PUT method implementation:
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)
}
}
But if I send a PUT request passing the same exact fields that I got in the GET response body, with the creation date formatted as a string, I get this error:
{
"error": true,
"reason": "Could not convert to `Double`: str(\"2020-05-27T15:24:41Z\")"
}
It's expecting a double. If I try sending the number of seconds after 1970 it works, but I don't understand why the same date object is encoded using a string date and decoded using a double. How to go around this problem?
Using Vapor 4, I specified a custom JSONDecoder
. This can be done globally, or as shown here for a single request.
In this scenario, I was decoding a POST'ed struct GetLogsRequest
that included a date field.
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let request = try req.content.decode(GetLogsRequest.self, using: decoder)
See https://docs.vapor.codes/4.0/content/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With