在 SwiftUI 中显示 JSON 数据

Displaying JSON Data in SwiftUI

我目前正在开发一个使用 OpenWeatherMap OneCall API 显示天气的应用程序,但我正在努力弄清楚如何显示数据。当我尝试在列表中显示它时,结果只是一个空白列表,没有任何错误消息或任何内容。

这是我的天气结构:

import Foundation

struct Weather: Codable {
    var lat: Double
    var lon: Double
    var timezone: String
    var timezone_offset: Int
    var current: Current
    var hourly: [Hourly]
    var daily: [Daily]
}

struct Current: Codable {
    var dt: Int
    var sunrise: Int
    var sunset: Int
    var temp: Double
    var feels_like: Double
    var pressure: Int
    var humidity: Int
    var dew_point: Double
    var uvi: Double
    var clouds: Int
    var visibility: Int
    var wind_speed: Double
    var wind_deg: Int
    var weather: [WeatherData]
    var rain: Double
}

    struct WeatherData: Codable {
        var id: Int
        var main: String
        var description: String
        var icon: String
    }

struct Hourly: Codable, Identifiable {
    var id = UUID()
    var dt: Int
    var temp: Double
    var feels_like: Double
    var pressure: Int
    var humidity: Int
    var dew_point: Double
    var clouds: Int
    var wind_speed: Double
    var wind_deg: Int
    var weather: [WeatherData]
    var rain: Double
}

struct Daily: Codable {
    var dt: Int
    var sunrise: Int
    var sunset: Int
    var temp: TempDetail
    var feels_like: FeelsLikeDetail
    var pressure: Int
    var humidity: Int
    var dew_point: Double
    var wind_speed: Double
    var wind_deg: Double
    var weather: [WeatherData]
    var clouds: Int
    var rain: Double
}

    struct TempDetail: Codable {
        var day: Double
        var min: Double
        var max: Double
        var night: Double
        var eve: Double
        var morn: Double
    }

struct FeelsLikeDetail: Codable {
    var day: Double
    var night: Double
    var eve: Double
    var morn: Double
}

这是我尝试 API 请求和 JSON 解码:

import SwiftUI

struct ContentView: View {
    @State var hourly = [Hourly]()
    
    func loadData() {
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/onecall?lat=40.7128&lon=74.0060&units=metric&appid=e69debdf0100132e2076aae6d1c80a2b") else {
            print("Invalid URL")
            return
        }
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(Weather.self, from: data) {
                    DispatchQueue.main.async {
                        self.hourly = decodedResponse.hourly
                    }
                    return
                }
            }
            
            print("Fetch Failed: \(error?.localizedDescription ?? "Unknown Error")")
            
        }.resume()
        
    }
    
    var body: some View {
        
        
        List(hourly) { item in
            Text("\(item.temp)")
        }.onAppear(perform: loadData)
        }
    }

struct WeatherAPI_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

这个问题与 SwiftUI 没有特别的关系。

主要问题是,如果添加不得解码的结构成员(id 每小时),则必须指定 CodingKeys。

另一个问题是 rainDailyHourly 中是可选的,在 Hourly 中是字典。

强烈建议处理任何错误并打印实际的 error 实例。你应该得到

keyNotFound(CodingKeys(stringValue: "id", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "hourly", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: "id", intValue: nil) ("id").", underlyingError: nil))

不需要URLRequest

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

        if let error = error { print(error); return }
        do {
           let decodedResponse = try JSONDecoder().decode(Weather.self, from: data!)
           DispatchQueue.main.async {
              self.hourly = decodedResponse.hourly
           }
        } catch { print(error) }
        
   }.resume()

注意:没有理由将所有结构成员都声明为变量。将它们声明为常量 (let)