JSON декодируемый swift 4

У меня ужасное время при создании публичной структуры для следующего JSON. Я пытаюсь извлечь температуру и влажность. Я пытался извлечь следующий JSON, но я думаю, что у меня проблема с тем, как я идентифицирую каждую из переменных.

Вот JSON:

{"coord":{"lon":-82.26,"lat":27.76},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"base":"stations","main":{"temp":66.24,"pressure":1021,"humidity":63,"temp_min":62.6,"temp_max":69.8},"visibility":16093,"wind":{"speed":8.05,"deg":80},"clouds":{"all":90},"dt":1523500500,"sys":{"type":1,"id":726,"message":0.0051,"country":"US","sunrise":1523531237,"sunset":1523577156},"id":420006939,"name":"Brandon","cod":200}

И вот структура

public struct Page: Decodable {

private enum CodingKeys : String, CodingKey {
    case coord = "coord", weather = "weather", mainz = "main", visibility = "visibility", wind = "wind", clouds = "clouds", dt = "dt", sys = "sys", id = "id", name = "name", cod = "cod"}

let coord: String
let weather: [String]
let mainz: String
let visibility: Int
let wind: String
let clouds: String
let dt: Int
let sys: String
let id: Int
let name: String
let cod: Int


public struct Main: Decodable {
    private enum CodingKeys : String, CodingKey {
        case temp = "temp", pressure = "pressure",humidity = "humidity", temp_min = "temp_min", temp_max = "temp_max"
    }
    let temp: Int
    let pressure: Int
    let humidity: Int
    let temp_min: Int
    let temp_max: Int
}

... и код, который я использую декодирования...

     //             Make the POST call and handle it in a completion handler
    let task =  session.dataTask(with: components.url!, completionHandler: {(data, response, error) in
        guard let data = data else { return }
        do
        {

            let result = try JSONDecoder().decode(Page.self, from: data)

            for main in result.mainz {
               print(main.humidity)

            }

        }catch

        {print("Figure it out")

        }



    })
    task.resume()

1 ответ

Решение

Создавайте структуры, чтобы захватывать все, что вы хотите. Например, если вас интересуют температуры и координаты, создайте структуры для них:

struct WeatherTemperature: Codable {
    let temp: Double
    let pressure: Double
    let humidity: Double
    let tempMin: Double
    let tempMax: Double
}

struct WeatherCoordinate: Codable {
    let latitude: Double
    let longitude: Double

    enum CodingKeys: String, CodingKey {
        case latitude = "lat"
        case longitude = "lon"
    }
}

Затем создайте структуру для всего ответа:

struct ResponseObject: Codable {
    let coord: WeatherCoordinate
    let main: WeatherTemperature
}

Обратите внимание, я создаю свойства только для тех ключей, которые мне нужны.

А затем расшифровать его:

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

do {
    let responseObject = try decoder.decode(ResponseObject.self, from: data)
    print(responseObject.coord)
    print(responseObject.main)
} catch {
    print(error)
}

Это привело к:

WeatherCoordinate # 1 (широта: 27.760000000000002, долгота: -82.260000000000005)

WeatherTeuration #1(temp: 66.239999999999995, давление: 1021.0, влажность: 63.0, tempMin: 62.600000000000001, tempMax: 69.799999999999997)

Ясно, что добавьте любые другие структуры / свойства, которые вас интересуют, но, надеюсь, это иллюстрирует идею.

Обратите внимание, я бы предпочел не позволять JSON диктовать имена моих свойств, поэтому, например, я определил стратегию декодирования ключа для моего декодера для преобразования из JSON snake_case в Swift camelCase.

Мне также нравятся более длинные имена свойств, поэтому, где я хотел более выразительные имена (latitude а также longitude скорее, чем lat а также lon) Я определил CodingKeys для тех. Но делай что хочешь на этот счет.

Другие вопросы по тегам