【问题标题】:JSON decodable swift 4JSON可解码swift 4
【发布时间】:2018-04-12 23:24:48
【问题描述】:

我在为以下 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()

【问题讨论】:

  • 首先你需要知道如何阅读 JSON。查看 JSON 中的第一件事:"coord":{"lon":-82.26,"lat":27.76}。好吧,那个叫做"coord" 的东西不是字符串;这是一本字典。但是您将coord 输入为字符串。所以这永远不会成功。 ——我可以继续,但是需要继续的人。想想每件事的类型。

标签: json swift4 decode xcode9.2


【解决方案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)

WeatherTemperature #1(温度:66.239999999999995,压力:1021.0,湿度:63.0,tempMin:62.600000000000001,tempMax:69.799999999999997)

显然,添加您关心的任何其他结构/属性,但希望这能说明这个想法。

注意,我不想让 JSON 指示我的属性名称,因此,例如,我为我的解码器指定了一个关键解码策略,以将 JSON snake_case 转换为 Swift camelCase。

我也喜欢更长的属性名称,所以我想要更具表现力的名称(latitudelongitude 而不是 latlon),我为它们定义了 CodingKeys。但是在这个分数上随心所欲。

【讨论】:

  • 感谢您提供此故障。它不仅帮助我回答了这个问题,而且了解了未来解码 JSON 的最佳方式。再次感谢。
猜你喜欢
  • 2019-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多