我正在使用 SwiftUI 和 Combine 進行登錄。當用戶輸入不正確的電子郵件或密碼時,您能否給我一些想法如何解碼和顯示 json 錯誤?我只能得到令牌。
當我使用不正確的電子郵件或密碼執行相同的登錄請求時,服務器向我回傳此錯誤訊息:
{
"code": "[jwt_auth] incorrect_password",
"message": "Incorrect password!",
"data": {
"status": 403
}
}
問題是我無法理解在Combine 中執行一個請求時如何解碼兩個不同的json 回應?我只能得到令牌。
這是登錄請求的模型:
struct LoginResponse: Decodable {
let token: String }
struct ErrorResponse: Decodable {
let message: String
}
struct Login: Codable {
let username: String
let password: String
}
static func login(email: String, password: String) -> AnyPublisher<LoginResponse, Error> {
let url = MarketplaceAPI.jwtAuth!
var request = URLRequest(url: url)
let encoder = JSONEncoder()
let login = Login(username: email, password: password)
let jsonData = try? encoder.encode(login)
request.httpBody = jsonData
request.httpMethod = HTTPMethod.POST.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
return URLSession.shared
.dataTaskPublisher(for: request)
.print()
.receive(on: DispatchQueue.main)
.map(\.data)
.decode(
type: LoginResponse.self,
decoder: JSONDecoder())
.eraseToAnyPublisher()
}
在視圖模型中:
MarketplaceAPI.login(email: email, password: password)
.sink(
receiveCompletion: { completion in
switch completion {
case .finished:
print("finished")
case .failure(let error):
print("Failure error:", error.localizedDescription) // This's returning token error
}
},
receiveValue: { value in
print("Token:", value.token)
}
})
.store(in: &subscriptions)
}
uj5u.com熱心網友回復:
我會ErrorResponse遵守Error協議:
struct ErrorResponse: Decodable, Error {
let message: String
}
然后,使用tryMap而不是decode(這是 的一種特殊情況tryMap)。
.tryMap({ data -> LoginResponse in
let decoder = JSONDecoder()
guard let loginResponse = try? decoder.decode(LoginResponse.self, from: data) else {
throw try decoder.decode(ErrorResponse.self, from: data)
}
return loginResponse
})
首先,嘗試將資料解碼為LoginResponse. 注意try?這里的使用。這樣我們就可以檢查這是否失敗。如果失敗,我們會拋出一個錯誤。我們拋出的錯誤是解碼為 的資料ErrorResponse,或者在解碼程序中拋出的任何錯誤。
在您的視圖模型中,您可以像這樣檢查錯誤:
.sink { completion in
switch completion {
case .failure(let error as ErrorResponse):
// wrong password/username
// you can access error.message here
case .failure(let error):
// some other sort of error:
default:
break
}
} receiveValue: { loginResponse in
...
}
uj5u.com熱心網友回復:
您可以使用tryMapwith combine 找出函式應該回傳的位置。我建議您閱讀有關它的檔案,但這里有一個片段,應該能夠讓您繼續使用它。
希望這就是您提出的問題的意思 - 我已經更改了一些內容,但可以隨意將代碼作為構建塊并根據需要進行調整!
enum LoginError: Error, Equatable {
case noConnection
case invalidResponse
}
static func login(email: String, password: String) -> AnyPublisher<Void, LoginError> {
return URLSession.shared
.dataTaskPublisher(for: request)
.print()
.receive(on: DispatchQueue.main)
.mapError { _ in LoginError.noConnection }
.tryMap { (data, response) in
guard let response = response as? HTTPURLResponse else {
throw LoginError.invalidResponse
}
if response.statusCode == 200 {
return data
} else {
throw LoginError.invalidResponse
}
}
.decode(type: LoginResponse.self, decoder: JSONDecoder())
.tryMap { [unowned self] in
// Update your session with the token here using $0 then return.
// e.g session.token = $0.token
return
}
.mapError { $0 as? LoginError ?? .invalidResponse }
.eraseToAnyPublisher()
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/401324.html
