在 API 请求中实现 Swift 结果<成功、错误>时遇到问题



我有意创建一个已经存在于MongoDB中的用户,以向用户显示错误消息,例如"请选择不同的用户名";或者"已在使用的电子邮件";但是我在解码服务器的响应时遇到了麻烦。

我的模型被设计用来处理成功(用户/令牌)或错误响应(消息)…

当在后端创建帐户时,我能够成功解码用户对象…

我做错了什么?我觉得我应该以某种方式使用枚举的错误模型??

// POSTMAN RESPONSE WHEN USERNAME ALREADY TAKEN
{
"success": false,
"message": "Please choose a different username"
}
// XCODE ERROR MESSAGE 
//...Expected to decode Dictionary<String, Any> but found a string/data 
//instead.", underlyingError: nil))
// DATA MODELS
struct UserResponse: Decodable {
let success: Bool
let message: ErrorResponse?
var user: User?
var token: String?
}
struct ErrorResponse: Decodable, Error {
let message: String
}
class LoginService {

static func createAccount(username: String, email: String, password: String, 
completion: @escaping(Result <UserResponse, Error>) -> Void) {

let user = UserSignup(username: username, email: email, password: password)

// Create URL code

do {
let encoder = JSONEncoder()
urlRequest.httpBody = try encoder.encode(user)

let dataTask = URLSession.shared.dataTask(with: urlRequest) { data, response, error in

if let error = error {
completion(.failure(error))
return
}
guard let jsonData = data else { return }

do {
let responseObject = try JSONDecoder().decode(UserResponse.self, from: jsonData)
switch responseObject.success {
case true:
completion(.success(responseObject))
case false:
// not working
guard let errorMessage = responseObject.message else {
return
}
completion(.failure(errorMessage))
}
} catch {
print(error)
}
}
dataTask.resume()
} catch {
// handle error
}
}

错误提示message为字符串,因此将其声明为String

struct UserResponse: Decodable {
let success: Bool
let message: String?
var user: User?
var token: String?
}

我觉得我应该为错误模型使用enum

去掉可选选项是个好主意。枚举首先解码status,根据值成功解码usertoken,失败解码错误message

struct UserResponse {
let user: User
let token: String
}
enum Response : Decodable {
case success(UserResponse)
case failure(String)

private enum CodingKeys : String, CodingKey { case success, message, user, token }

init(from decoder : Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let success = try container.decode(Bool.self, forKey: .success)
if success {
let user = try container.decode(User.self, forKey: .user)
let token = try container.decode(String.self, forKey: .token)
self = .success(UserResponse(user: user, token: token))
} else {
let message = try container.decode(String.self, forKey: .message)
self = .failure(message)
}
}
}

那么你可以替换

let responseObject = try JSONDecoder().decode(UserResponse.self, from: jsonData)
switch responseObject.success {
case true:
completion(.success(responseObject))
case false:
// not working
guard let errorMessage = responseObject.message else {
return
}
completion(.failure(errorMessage))
}

let response = try JSONDecoder().decode(Response.self, from: jsonData)
switch response {
case .success(let responseObject):
completion(.success(responseObject))
case .failure(let errorMessage)
completion(.failure(errorMessage))
}

最新更新