Adding a Date property to the model

What encoding and decoding special code needs to be added to the server app when a model includes a Swift Date property? Eg, say you add a Date property to Acronym to track the first time this acronym came into popular use. When I send a request to create an acronym the Vapor app reports
[ ERROR ] DecodingError.typeMismatch: POST /api/acronyms Value of type ‘String’ required for key ‘dateOfFirstReportedUse’. (ErrorMiddleware.swift:26)

Thanks!

What does your Acronym model look like and are you expecting it to be sent in the create request or added after?

The Date property will be set at the time of creation of the object. I simply added the (contrived) property to the model as such.

final class Acronym: Codable {
  var id: Int?
  var short: String
  var long: String
  var dateOfFirstReportedUse: Date
  var userID: UUID

  init(short: String, long: String, dateOfFirstReportedUse: Date, userID: UUID) {
    self.short = short
    self.long = long
    self.dateOfFirstReportedUse = dateOfFirstReportedUse
    self.userID = userID
  }
}

So if you want to create it outside of the POST request, you can just do:

let user = try req.requireAuthenticated(User.self)
let acronym = try Acronym(short: createData.short, long: createData.long, dateOfFirstReportedUse: Date(), userID = user.requireID())

Or if you wanted to send it in the POST request it would look like:

{
    ...
    "dateOfFirstReportedUse": "2020-04-02T13:00:00Z"
}
2 Likes

What I needed to do is customize the content encoding/decoding for Date objects like this;

  1. Create a content.swift file in the cloud app project with this function:
public func content(config: inout ContentConfig) throws {
	let encoder = JSONEncoder()
	let decoder = JSONDecoder()

	encoder.dateEncodingStrategy = .secondsSince1970
	decoder.dateDecodingStrategy = .secondsSince1970

	config.use(encoder: encoder, for: .json)
	config.use(decoder: decoder, for: .json)
}
  1. Add this to configure.swift:
/// Register Content Config
var contentConfig = ContentConfig.default()
try content(config: &contentConfig)
services.register(contentConfig)
  1. In the iOS app set the dateEncodingStrategy property of the JSONEncoder. For example,
    in ResourceRequest.swift’s save function:
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .secondsSince1970

@gonzalo Do you still have issues with this?

No longer an issue. I solved it as described above.