【问题标题】:Swift - Different output based on JSON response contentsSwift - 基于 JSON 响应内容的不同输出
【发布时间】:2020-04-02 00:33:16
【问题描述】:

这个问题可能会被认为是非常基本的,并且可能可以通过搜索找到,但是尽管我努力搜索 StackOverflow 并且只是谷歌,但我找不到任何关于如何的最新线程或帖子处理 REST API 的不同响应,并且,正如我所发现的,拥有一个最新的线程对于在发生错误时避免麻烦很重要。因此,要进入它,我的服务器上有一个用于登录的 API 端点。正如人们所假设的那样,它会响应给定登录凭据的两种情况;

如果登录信息成功,则返回这个JSON Object:

{
    "user": {
        "id": 1,
        "type": "user",
        "name": "username",
        "api_token": "accesstokenhere"
    },
    "access_token": "accesstokenhere"
}

如果不成功,它会给出这个响应

{
    "message": "Invalid credentials"
}

现在我有我的应用程序的登录屏幕,按“登录”后,将信息提交到服务器并获取此响应,这没有问题并且有据可查。到目前为止,我有以下代码:

import SwiftUI
import Combine
import Foundation

public struct UserModel: Decodable {
    let id: Int
    let username: String
    let age: Int

    enum CodingKeys: String, CodingKey {
        case id = "id"
        case username = "name"
        case age = "age"
    }
}

public struct UserResponse: Decodable {
    public let user: UserModel
    public let accessToken: String

    enum CodingKeys: String, CodingKey {
        case user = "user"
        case accessToken = "access_token"
    }
}


public class UserFetcher: ObservableObject {
    public let objectWillChange = PassthroughSubject<UserFetcher,Never>()

    @Published var hasFinished: Bool = false {
        didSet {
            objectWillChange.send(self)
        }
    }
    var user: UserResponse?

    @Published var incorrectLogin: Bool = false {
        didSet {
            objectWillChange.send(self)
        }
    }

    init(){
        guard let url = URL(string: "https://mywebsite.com/api/login") else { return }

        var urlRequest = URLRequest(url: url)
        urlRequest.httpMethod = "POST"

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

            do {
                if let d = data {
                    let decodedRes = try JSONDecoder().decode(UserResponse.self, from: d)
                    DispatchQueue.main.async {
                        self.user = decodedRes
                        self.hasFinished = true
                        print("Dispatching")
                    }
                } else {
                    print("No Data")
                }
            } catch {
                print("Error")
            }

        }.resume()
    }
}

我已经完整地阅读了这一部分,除了一些小的调整以适应我为类似任务而拥有的另一个文件中的不同对象,尽管它没有替代响应,因此我不必处理任何其他类型的数据响应。

我对 swift 还很陌生,所以我对 do-try-catch 语法有基本的了解,但我不知道如何捕获不同的响应模型或将它们放在我的代码中的什么位置以防止任何错误正在发生。

理想情况下,我希望它切换不正确的登录变量,可以观察到该变量并触发一个弹出窗口,显示不正确的登录信息,就像所有登录屏幕在您输入不正确的凭据时所做的那样。如果没有,它应该只切换 hasFinished 变量并将不正确的登录保留为 false,然后我将使用用户模型来完成所有幕后工作。

再说一次,我对 swift 还很陌生,我确定这里可能存在安全问题或其他我忽略的问题,如果是这种情况,请告诉我。

【问题讨论】:

    标签: json swift rest


    【解决方案1】:

    一个合适的解决方案是一个带有关联类型的枚举。

    为错误情况添加一个结构

    public struct ErrorResponse: Decodable {
        let message : String
    }
    

    和枚举

    enum Response : Decodable {
    
        case success(UserResponse)
        case failure(ErrorResponse)
    
        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            do {
                let userData = try container.decode(UserResponse.self)
                self = .success(userData)
            } catch DecodingError.typeMismatch {
                let errorData = try container.decode(ErrorResponse.self)
                self = .failure(errorData)
            }
        }
    }
    

    解码后数据switch上的结果并进行处理

    do {
        if let d = data {
            let result = try JSONDecoder().decode(Response.self, from: d)
            switch result {
                case .success(let userData):
                    DispatchQueue.main.async {
                        self.user = userData
                        self.hasFinished = true
                        print("Dispatching")
                    }
                case .success(let errorData):
                    print(errorData.message)
                // handle the error
            }
    
        } else {
            print("No Data")
        }
    } catch {
        print(error) // never print a meaningless literal string in a Decoding catch block
    }
    

    【讨论】:

      猜你喜欢
      • 2014-10-07
      • 2014-12-07
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 2020-08-25
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      相关资源
      最近更新 更多