1

With Swift 5 I'm trying to cut a lot of my dependencies (Alamofire), and I'm trying to understand how can I do a multipart request while using Codable and URLRequest

My code is working correctly for creating an user with a name and email, but I need to add an avatar to the struct.

After adding the avatar, how can I encode the struct in order to be a multipart request. I found some solutions online but not for scenarios like the one I'm trying to implement.

The code below is the working code for the request without an Avatar.

struct User: Codable {
    let name: String
    let email: String?
}
var endpointRequest = URLRequest(url: endpointUrl)
endpointRequest.httpMethod = "POST"
endpointRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
do {
   endpointRequest.httpBody = try JSONEncoder().encode(data)
} catch {
   onError(nil, error)
   return
}


URLSession.shared.dataTask(
    with: endpointRequest,
    completionHandler: { (data, urlResponse, error) in
        DispatchQueue.main.async {
            self.processResponse(data, urlResponse, error, onSuccess: onSuccess, onError: onError)
        }
}).resume()

jfredsilva
  • 1,434
  • 1
  • 9
  • 15

1 Answers1

-1

UIImage does not conform to Codable but you can encode the pngData representation. However this requires to implement the Codable methods

struct User: Codable {
    let name: String
    let email: String?
    var avatar : UIImage?

    private enum CodingKeys : String, CodingKey { case name, email, avatar }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        email = try container.decodeIfPresent(String.self, forKey: .email)
        if let avatarData = try? container.decode(Data.self, forKey: .avatar) {
            avatar = UIImage(data: avatarData)
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(name, forKey: .name)
        try container.encode(email, forKey: .email)
        if let avatarImage = avatar {
            try container.encode(avatarImage.pngData(), forKey: .avatar)
        }
    }
}

Or declare avatar as URL and send the image separately

vadian
  • 274,689
  • 30
  • 353
  • 361