Reputation: 952
I need to send a request inside a key, expecting it to look like so:
{
"user": {
"email": String,
"password": String
}
}
I am trying to do this via creating a UserSignupRequest
that has email and password properties and conforms to codable:
struct UserSignupRequest: Codable {
let email: String
let password: String
enum CodingKeys: String, CodingKey {
case email
case password
}
}
Then creating the parameters for alamofire via:
case .signup(let request):
return ["user": request]
}
My logic was this will create the child key value pairs inside a user parent key, however my app fatal errors with errors when trying:
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
Im sure the solution is something simple, but I cant quite get it to work! many thanks
Upvotes: 1
Views: 147
Reputation: 2875
JSONSerialization
works only with simple types as arrays, dictionaries, strings, numbers, etc.
If you want to use it, then you don't need Codable
, instead you need function func toDict() -> [String: Any]
that will convert your UserSignupRequest
to dictionary.
Then your switch will be look like:
case .signup(let request):
return ["user": request.toDict()]
}
JSONSerialization
is old api and if you planning to use Codable
you need to use:
urlRequest.httpBody = try JSONEncoder().encode(parameters)
I assume you getting parameters like:
func parameters(for request: RequestType) -> [String: Any] {
switch request {
case .signup(let request):
return ["user": request]
}
}
So when you pass your parameters in encoder he doesn't know what type to encode.
TO solve we can return not just Dictionary, but specific protocol / type aka:
protocol Request {
func encode(by encoder: JSONEncoder) throws -> Data
}
extension Request where Self: Encodable {
func encode(by encoder: JSONEncoder) throws -> Data {
/// since it will be method on specific type, JSONEncoder will know what type is encoding
return try encoder.encode(self)
}
}
struct UserSignupRequest: Codable, Request {
struct RequestData: Codable {
let email: String
let password: String
}
let data: RequestData
enum CodingKeys: String, CodingKey {
case data = "user"
}
}
func parameters(for request: RequestType) -> Request {
switch request {
case .signup(let requestData):
return UserSignupRequest(data: requestData)
}
}
So now you can do
urlRequest.httpBody = try parameters.encode(by: JSONEncoder())
Upvotes: 2