简体   繁体   English

Swift4、JSON、keyNotFound、没有与键关联的值

[英]Swift4, JSON, keyNotFound, No value associated with key

I need to do Sunset Sunrise App, and this is my code.我需要做 Sunset Sunrise App,这是我的代码。 But I have this error:但我有这个错误:

Error serializing json: keyNotFound(Sunrise_Sunset.SunPosition.Results.(CodingKeys in _B4291256871B16D8D013EC8806040532).sunrise, Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key sunrise (\\"sunrise\\").", underlyingError: nil))错误序列化 json: keyNotFound(Sunrise_Sunset.SunPosition.Results.(CodingKeys in _B4291256871B16D8D013EC8806040532).sunrise, Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key sunrise\\").\\"底层错误:无))

And I don't understand how to fix it.我不明白如何解决它。 Maybe someone had this problem.也许有人有这个问题。 I will be grateful for any help) This is the API, which I have: https://sunrise-sunset.org/api如有任何帮助,我将不胜感激)这是我拥有的 API: https : //sunrise-sunset.org/api

struct SunPosition: Codable {
struct Results: Codable {
    let sunrise: String
    let sunset: String
    let solarNoon: String
    let dayLenght: String
    let civilTwilightBegin: String
    let civilTwilightEnd: String
    let nauticalTwilightBegin: String
    let nauticalTwilightEnd: String
    let astronomicalTwilightBegin: String
    let astronomicalTwilightEnd: String

    enum CodingKey:String, Swift.CodingKey {
        case sunrise = "sunrise"
        case sunset = "sunset"
        case solarNoon = "solar_noon"
        case dayLenght = "day_length"
        case civilTwilightBegin = "civil_twilight_begin"
        case civilTwilightEnd = "civil_twilight_end"
        case nauticalTwilightBegin = "nautical_twilight_begin"
        case nauticalTwilightEnd = "nautical_twilight_end"
        case astronomicalTwilightBegin = "astronomical_twilight_begin"
        case astronomicalTwilightEnd = "astronomical_twilight_end"
    }
  }
}

extension SunPosition.Results {
init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    sunrise = try values.decode(String.self, forKey: .sunrise)
    sunset = try values.decode(String.self, forKey: .sunset)
    solarNoon = try values.decode(String.self, forKey: .solarNoon)
    dayLenght = try values.decode(String.self, forKey: .dayLenght)
    civilTwilightBegin = try values.decode(String.self, forKey: .civilTwilightBegin)
    civilTwilightEnd = try values.decode(String.self, forKey: .civilTwilightEnd)
    nauticalTwilightBegin = try values.decode(String.self, forKey: .nauticalTwilightBegin)
    nauticalTwilightEnd = try values.decode(String.self, forKey: .nauticalTwilightEnd)
    astronomicalTwilightBegin = try values.decode(String.self, forKey: .astronomicalTwilightBegin)
    astronomicalTwilightEnd = try values.decode(String.self, forKey: .astronomicalTwilightEnd)
}
}

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    let jsonUrlString = "https://api.sunrise-sunset.org/json?lat=36.7201600&lng=-4.4203400"
    guard let url = URL(string: jsonUrlString) else { return }

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

        guard let data = data else { return }

        do {
            let sunPosition = try JSONDecoder().decode(SunPosition.Results.self, from: data)
            print(sunPosition)
        }catch let jsonErr {
            print("Error serializing json:", jsonErr)
        }

    }.resume()
}
}

Four issues:四个问题:

  1. Add let results : Results in the SunPosition struct.添加let results : ResultsSunPosition结构中的let results : Results
  2. Typo: private enum CodingKeys: String, CodingKey rather than enum CodingKey :String, Swift.CodingKey , note the singular / plural difference, the private attribute is recommended but does not cause the issue. private enum CodingKeys: String, CodingKeyprivate enum CodingKeys: String, CodingKey而不是enum CodingKey :String, Swift.CodingKey ,注意单数/复数区别,推荐使用private属性但不会导致问题。
  3. Wrong type to decode: JSONDecoder().decode(SunPosition.self, from: data) rather than JSONDecoder().decode(SunPosition.Results.self, from: data) .要解码的错误类型: JSONDecoder().decode(SunPosition.self, from: data)而不是JSONDecoder().decode(SunPosition.Results.self, from: data)
  4. To get the results you have to print(sunPosition.results) .要获得results您必须print(sunPosition.results)

Three notes:三注意事项:

  1. Delete the entire extension.删除整个扩展。 In this case you get the initializer for free.在这种情况下,您可以免费获得初始化程序。
  2. Add &formatted=0 to the URL and set the dateDecodingStrategy of the decoder to .iso8601 to get Date objects.在 URL 中添加&formatted=0并将解码器的dateDecodingStrategy设置为.iso8601以获取Date对象。 Change the type of all date related properties from String to Date and the type of dayLenght from String to TimeInterval .将所有与日期相关的属性的类型从String更改为Date ,将dayLenght的类型从String更改为TimeInterval To change dateDecodingStrategy write改变dateDecodingStrategy

    let decoder = JSONDecoder() decoder.dateDecodingStrategy = .iso8601 let sunPosition = try decoder.decode(SunPosition.self ...
  3. I recommend to handle the status , too.我也建议处理status Add this in the SunPosition struct将此添加到SunPosition结构中

    let status : String var success : Bool { return status == "OK" }

为了排除它,如果由于某种原因您的端点返回错误消息或零数据,您将收到此错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM