I’m working on an authentication system where one API endpoint returns different JSON structures based on whether login succeeds or fails. When authentication works, I get user data like this:
[
{
"userId": 456,
"username": "TestUser",
"userEmail": "[email protected]",
"active": "1"
}
]
When authentication fails, the response looks like:
[
{
"errorText": "Authentication failed",
"active": "0"
}
]
My current approach uses a single struct but crashes when trying to decode the error response:
struct AuthResponse: Codable {
let userId: Int
let username: String
let userEmail: String
let active: String
let errorText: String
enum CodingKeys: String, CodingKey {
case userId = "userId"
case username = "username"
case userEmail = "userEmail"
case active = "active"
case errorText = "errorText"
}
}
func authenticateUser() {
let userEmail = emailInput.text!
let userPass = passwordInput.text!
guard let endpoint = URL(string: authAPI) else { return }
URLSession.shared.dataTask(with: endpoint) { (data, response, error) in
guard let data = data else { return }
do {
let result = try JSONDecoder().decode([AuthResponse].self, from: data)
let statusList = result.map { $0.active }
if statusList.contains("1") {
print("Authentication successful")
DispatchQueue.main.async {
self.navigateToMainScreen()
}
} else if statusList.contains("0") {
DispatchQueue.main.async {
self.showErrorAlert()
}
}
} catch {
print(error)
}
}.resume()
}
I get a keyNotFound error because the failure response doesn’t contain userId, username, or userEmail fields. How can I properly handle these two different JSON structures from the same endpoint?