我对开发应用程序、使用 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/