json - 如何在 SwiftUI 中解码来自 API 的 JSON 响应以在 View 中使用

标签 json swift api swiftui

我对开发应用程序、使用 Xcode 和 Swift 以及尝试了解如何解码来自 API 的 JSON 响应还很陌生。我也在尝试遵循 MVVM 实践。

我调用的 API 返回的数据结构如下:

"location": {
    "latitude": -27.4748,         
    "longitude": 153.017     },     
"date": "2020-12-21",     
"current_time": "21:55:42.198",     
"sunrise": "04:49",     
"sunset": "18:42",
"...": "..."
} 

我的理解是我需要一个结构来将这些信息解码成。这是我的结构的样子(可能不正确):

struct Example: Decodable {
let location: Coordinates
let date: String
let current_time: String
let sunset: String
let sunset: String
let ... :String

struct Coordinates: Decodable{
    let latitude: Double
    let longitude: Double
    }
}

所以我希望能够调用这个 api。我有正确的地址来调用它,因为我正在使用的网站上的仪表板显示我已经点击了它。我能得到一些关于如何调用它和解码响应的指导吗?目前我正在做这样的事情:

if let url = URL(string: "this is the api web address"){
    URLSession.shared.dataTask(with: url){ (with: data, options [] ) as?                 
[String:String]{
        print("(\json)" + "for debugging purposes")
}}
else{
    print("error")
}
.resume()

感谢您提供的所有帮助。同样,我的目标是调用此函数、访问 API、解码 JSON 响应并将其存储到我可以在其他地方的 View 中使用的变量中。谢谢!

最佳答案

您将 JSONSerialization 与 Codable 和 URLSession 混合在一起。忘记 JSONSerialization。尽量关注 Codable 协议(protocol)。

struct Example: Decodable {
    let location: Coordinates
    let date: String
    let currentTime: String
    let sunrise: String
    let sunset: String
}

struct Coordinates: Decodable {
    let latitude: Double
    let longitude: Double
}

这是同步解码 json 数据的方法

extension JSONDecoder {
    static let shared: JSONDecoder = {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decoder.dateDecodingStrategy = .iso8601
        return decoder
    }()
}

extension Data {
    func decodedObject<T: Decodable>() throws -> T {
        try JSONDecoder.shared.decode(T.self, from: self)
    }
}

Playground 测试

let json = """
{
    "location": {
        "latitude": -27.4748,
        "longitude": 153.017     },
    "date": "2020-12-21",
    "current_time": "21:55:42.198",
    "sunrise": "04:49",
    "sunset": "18:42",
}
"""

let data = Data(json.utf8)

do {
    let example: Example = try data.decodedObject()
    print(example)
} catch {
    print(error)
}

异步获取数据


extension URL {
    func getResult<T: Decodable>(completion: @escaping (Result<T, Error>) -> Void) {
        URLSession.shared.dataTask(with: self) { data, response, error in
            guard let data = data, error == nil else {
                completion(.failure(error!))
                return
            }
            do {
                completion(.success(try data.decodedObject()))
            } catch {
                completion(.failure(error))
            }
        }.resume()
    }
}

let url = URL(string: "https://www.example.com/whatever")!

url.getResult { (result: Result<Example, Error>) in
    switch result {
    case let .success(example):
        print(example)
    case let .failure(error):
        print(error)

    }
}

如果您在实现 MVVM 的 SwiftUI 项目方面需要帮助,请随时提出新问题。

关于json - 如何在 SwiftUI 中解码来自 API 的 JSON 响应以在 View 中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67643196/

相关文章:

swift - 将协议(protocol)扩展限制为单个枚举情况

Java编译器已完成但未创建可执行文件?

java - 创建 REST/JSON API

android - 在 ListView 中显示图像,如果文件特定文件已下载内部存储

javascript - 使用 Angular 进行动态路由 - 如何使用此 JSON?

java - 如何从Gson获取变量的值

javascript - 从 json 数组文件中检索键(动态)并将其用于 d3js 函数

ios - 错误 : Extra argument in call

ios - 当 iPad 旋转时,ActionSheet 的 PopoverController 不会停留在窗口的中心

api - 我如何知道使用 Azure 存储的代码是否会受到 2015 年 12 月即将删除的 API 版本的影响?