如何在数组中组织JSON结构

时间:2018-08-22 16:48:17

标签: ios json swift

我以前使用过JSON结构,并设法使它们与其他API一起使用,但是此API的JSON数据略有不同,它似乎将数据包含在称为“ List”的数组中。我认为下面的结构格式不正确吗?当我运行该应用程序时,我没有收到任何错误消息,但是我尝试更改,不变的Label值也不会更改,“ Test”的值也不会打印到控制台。我试图调用Description值并将其打印到标签上。

JSON结构如下:

struct MyForecast : Decodable {
    let cod : String
    let message : Double
    let cnt : Int
    let list : [List]
    let city : Cityy
    let coordinate : Coordi
}

struct Coordi : Decodable {
    let lat, lon : Double
}

struct Cityy : Decodable {
    let id, population : Int
    let name, country : String
    let coord : Coordinate
}

struct Mainn : Decodable {
    let temp, tempMin, tempMax : Double
    let seaLevel, grndLevel, tempKf: Double
    let pressure, humidity : Int
}

struct Windd : Decodable {
    let speed : Double
    let deg : Double
}

struct Weatherr : Decodable {
    let id : Int
    let icon : String
    let main : MainEnum
    let description: String
}

struct List : Decodable {
    let dt : Date
    let main : MainForecast
    let weather : [Weatherr]
    let clouds : Cloudss
    let wind : Windd
    let sys : Syss
    let dtTxt : String
    let rain: Rainn?
    let city: Cityy
}

struct Syss : Decodable {
    let pod: Pod
}

struct MainForecast : Decodable {
    let temp, tempMin, tempMax, pressure, seaLevel, grndLevel, humidity, tempKf : Double?
}

struct Cloudss : Decodable {
    let all : Int
}

struct Rainn: Codable {
    let the3H: Double?

    enum CodingKeys: String, CodingKey {
        case the3H = "3h"
    }
}

enum Pod: String, Codable {
    case d = "d"
    case n = "n"
}

enum MainEnum: String, Codable {
    case clear = "Clear"
    case clouds = "Clouds"
    case rain = "Rain"
}

下面的ViewController:

class ForecastViewController: UIViewController {


    @IBOutlet weak var testLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()


        guard let APIUrl = URL (string: "https://api.openweathermap.org/data/2.5/forecast?q=London&APPID=***APIKEY***&units=metric") else { return }
        //API KEY


    URLSession.shared.dataTask(with: APIUrl) { data, response, error in
        guard let data = data else { return }


        let decoderr = JSONDecoder()

        do {

            decoderr.keyDecodingStrategy = .convertFromSnakeCase
            decoderr.dateDecodingStrategy = .secondsSince1970

        let forecastData = try decoderr.decode(MyForecast.self, from: data)

        if let test = forecastData.list.first?.city.name { //using .first because Weather is stored in an array
            let description = test.description
            print(description)
            DispatchQueue.main.async {
                self.testLabel.text! = description
            }
        }

            else
                {
                    print("weather not found")
                }

        } catch {
            print(error.localizedDescription)
        }
        }.resume()

1 个答案:

答案 0 :(得分:1)

您的结构错误。在您编辑问题之前。

openweathermap.org的5天/ 3小时天气预报API发送与当前天气数据不同的JSON结构。

您可以自己轻松创建结构:

  • 下载Data
  • 从数据创建一个(JSON)字符串
  • 复制文本
  • 打开app.quicktype.io
  • 将文本粘贴到左侧的JSON文本字段中
  • 为根对象添加一个合适的名称。

quicktype.io为您创建结构。

预测结构为(Rain 完全没有可选项

struct MyForecast : Decodable {
    let cod : String
    let message : Double
    let cnt : Int
    let list : [List]
    let city : City
}

struct Coordinate : Decodable {
    let lat, lon : Double
}

struct City : Decodable {
    let id, population : Int
    let name, country : String
    let coord : Coordinate
}

struct Main : Decodable {
    let temp, tempMin, tempMax : Double
    let seaLevel, grndLevel, tempKf: Double
    let pressure, humidity : Int
}

struct Wind : Decodable {
    let speed : Double
    let deg : Double
}

struct Weather : Decodable {
    let id : Int
    let icon : String
    let main : MainEnum
    let description: String
}

struct List : Decodable {
    let dt : Date
    let main : MainForecast
    let weather : [Weather]
    let clouds : Clouds
    let wind : Wind
    let sys : Sys
    let dtTxt : String
    let rain: Rain?
}

struct Sys : Decodable {
    let pod: Pod
}

struct MainForecast : Decodable {
    let temp, tempMin, tempMax, pressure, seaLevel, grndLevel, humidity, tempKf : Double
}

struct Clouds : Decodable {
    let all : Int
}

struct Rain: Codable {
    let the3H: Double?

    enum CodingKeys: String, CodingKey {
        case the3H = "3h"
    }
}

enum Pod: String, Codable {
    case d, n
}

enum MainEnum: String, Codable {
    case clear = "Clear"
    case clouds = "Clouds"
    case rain = "Rain"
}

要解码结构,必须添加日期和密钥解码策略。

ListWeather是数组

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .secondsSince1970
let forecastData = try decoder.decode(MyForecast.self, from: data)
if let test = forecastData.list.first?.weather.first? { //using .first because Weather is stored in an array
    let description = test.description
    print(description)
    DispatchQueue.main.async {
        self.testLabel.text! = description
    }
} else { print("weather not found") }