Using JSONEncoder to encode a variable with Codable as type
Use a generic type constrained to Encodable
func saveObject<T : Encodable>(_ object: T, at location: String) { //Some code let data = try JSONEncoder().encode(object) //Some more code}
I would use a different approach to that extending the Encodable protocol with all the instance methods you might need. Expanding on that you can add a parameter to your methods to pass a custom encoder and provide a default encoder as well to all of them:
extension DataProtocol { var string: String? { String(bytes: self, encoding: .utf8) }}
extension Encodable { func data(using encoder: JSONEncoder = JSONEncoder()) throws -> Data { try encoder.encode(self) } func string(using encoder: JSONEncoder = JSONEncoder()) throws -> String { try data(using: encoder).string ?? "" }}
Usage
let message = ["key":["a","b","c"]]let jsonData = try! message.data() // 21 bytes [123, 34, 107, 101, 121, 34, 58, 91, 34, 97, 34, 44, 34, 98, 34, 44, 34, 99, 34, 93, 125]let jsonString = try! message.string() // "{"key":["a","b","c"]}"
Example when passing a date with a default encoder. Note that the dateEncodingStrategy used is the default (a Double representing the timeIntervalSinceReferenceDate):
let message = ["createdAt": Date()]let jsonData = try! message.data() // 33 bytes -> [123, 34, 99, 114, 101, 97, 116, 101, 97, 100, 65, 116, 34, 58, 53, 55, 49, 54, 49, 55, 56, 52, 49, 46, 52, 53, 48, 55, 52, 52, 48, 51, 125]let jsonString = try! message.string() // {"createdAt":571617841.45074403}"
Now you can pass a custom encoder to your method to format your Date in a human readable format:
let message = ["createdAt": Date()]let encoder = JSONEncoder()encoder.dateEncodingStrategy = .iso8601let jsonString = try! message.string(using: encoder) // "{"createdAt":"2019-02-11T22:48:19Z"}"
Now using a custom Message structure
struct Message: Codable { let id: Int let createdAt: Date let sender, title, body: String}
extension Encodable { func sendDataToServer(using encoder: JSONEncoder = JSONEncoder()) throws { print(self, terminator: "\n\n") // Don't handle the error here. Propagate the error. let data = try self.data(using: encoder) print(data.string!) // following the code to upload the data to the server print("Message was successfully sent") }}
let message = Message(id: 1, createdAt: Date(), sender: "user@company.com", title: "Lorem Ipsum", body: """Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.""")
let iso8601 = JSONEncoder()iso8601.dateEncodingStrategy = .iso8601iso8601.outputFormatting = .prettyPrinteddo { try message.sendDataToServer(using: iso8601)} catch { // handle all errors print(error)}
This will print
Message(id: 1, createdAt: 2019-02-11 23:57:31 +0000, sender: "user@company.com", title: "Lorem Ipsum", body: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."){ "body" : "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", "id" : 1, "sender" : "user@company.com", "title" : "Lorem Ipsum", "createdAt" : "2019-02-11T23:57:31Z"}now just add the code to send the json data to the server
You need to use generic function with generic type Encodable
You can't
func toData(object: Encodable) throws -> Data { let encoder = JSONEncoder() return try encoder.encode(object) // Cannot invoke 'encode' with an argument list of type '(Encodable)'}
You can
func toData<T: Encodable>(object: T) throws -> Data { let encoder = JSONEncoder() return try encoder.encode(object)}