Swift - 没有与键 CodingKeys 关联的值

Swift - No value associated with key CodingKeys

提问人:Summer 提问时间:9/19/2023 更新时间:9/19/2023 访问量:108

问:

当我尝试解析开放 API 返回的 JSON 响应时,我运行了此错误:

keyNotFound(CodingKeys(stringValue: “name”, intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: “没有与键关联的值 CodingKeys(stringValue: \”name\“, intValue: nil) (\”name\“).”, underlyingError: nil))

这发生在以下代码行中: 这是解码代码的一部分:let decodedWeatherData = try decoder.decode(WeatherData.self, from: data)

func parseWeatherJSON(data: Data) {
    let decoder = JSONDecoder()
    
    do {
        let decodedWeatherData = try decoder.decode(WeatherData.self, from: data)
        let id = decodedWeatherData.weather[0].id
        let temp = decodedWeatherData.main.temp
        let name = decodedWeatherData.name
        
        let weather = WeatherModel(conditionId: id, temperature: temp, cityName: name)
        print(weather.tempStr)
    } catch {
        print(error)
    }
}

这是我的 JSON 响应:

{
  "coord": {
    "lon": 121.4692,
    "lat": 31.2323
  },
  "weather": [
    {
      "id": 800,
      "main": "Clear",
      "description": "clear sky",
      "icon": "01n"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 25.48,
    "feels_like": 26.36,
    "temp_min": 23.86,
    "temp_max": 26.95,
    "pressure": 1011,
    "humidity": 87
  },
  "visibility": 10000,
  "wind": {
    "speed": 3,
    "deg": 140
  },
  "clouds": {
    "all": 0
  },
  "dt": 1695067161,
  "sys": {
    "type": 2,
    "id": 2043475,
    "country": "CN",
    "sunrise": 1695073210,
    "sunset": 1695117382
  },
  "timezone": 28800,
  "id": 1796231,
  "name": "Shanghai Municipality",
  "cod": 200
}

我的结构:WeatherData

struct WeatherData: Codable {
    let name: String
    let main: Main
    let weather: [Weather]
}

struct Main: Codable {
    let temp: Double
}

struct Weather: Codable {
    let description: String
    let id: Int
}

似乎我的结构与JSON响应相对应。我不知道为什么解码失败,无法关联 CodingKey

iOS JSON 斯威夫特

评论

2赞 Sweeper 9/19/2023
您确定 JSON 是正确的吗?尝试打印出来。String(data: data, encoding: .utf8)
0赞 workingdog support Ukraine 9/19/2023
您是否尝试过该属性是可选的?类似地,对于和var name: String?Main?[Weather]?
0赞 vadian 9/19/2023
实际上,这只有在您使用 API 而不是 API 时才会发生forecastweather
0赞 Larme 9/19/2023
替换为 ,这是一件好事,因此请将实际接收 JSON 与您的请求一起打印出来,因为您发布的请求来自...?因为它可能是请求中缺少参数,使其发送错误(JSON 错误、HTML 错误等)、错误的 URL 等......并向我们展示您尝试按照建议解码的真实 JSON,@vadian它可能是错误的 url/API......print(error)print("Error: \(error) while trying to decode: \(String(data: data, encoding: .utf8)")

答:

-1赞 Krishnapalsinh Gohil 9/19/2023 #1

解码是正确的。问题出在您从网络获取的数据中,除了JSON之外,可能还有其他一些字符,因此会引发此类错误。我从字符串中准备了数据只是为了演示。

let json = """
{
  "coord": {
    "lon": 121.4692,
    "lat": 31.2323
  },
  "weather": [
    {
      "id": 800,
      "main": "Clear",
      "description": "clear sky",
      "icon": "01n"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 25.48,
    "feels_like": 26.36,
    "temp_min": 23.86,
    "temp_max": 26.95,
    "pressure": 1011,
    "humidity": 87
  },
  "visibility": 10000,
  "wind": {
    "speed": 3,
    "deg": 140
  },
  "clouds": {
    "all": 0
  },
  "dt": 1695067161,
  "sys": {
    "type": 2,
    "id": 2043475,
    "country": "CN",
    "sunrise": 1695073210,
    "sunset": 1695117382
  },
  "timezone": 28800,
  "id": 1796231,
  "name": "Shanghai Municipality",
  "cod": 200
}
"""
let data = json.data(using: .utf8)
0赞 Elevo 9/19/2023 #2

列出的JSON是有效的,但错误表明当时服务器提供的JSON缺少密钥,因此出现了错误。name

  • 这效果很好
struct WeatherData: Codable {
    let name: String
    let main: Main
    let weather: [Weather]
}

struct Main: Codable {
    let temp: Double
}

struct Weather: Codable {
    let description: String
    let id: Int
}

func parseWeatherJSON(data: Data) {
    let decoder = JSONDecoder()
    
    do {
        let decodedWeatherData = try decoder.decode(WeatherData.self, from: data)
        print(decodedWeatherData)
    } catch {
        print(error)
    }
}

let jsonString = """
{
  "coord": {
    "lon": 121.4692,
    "lat": 31.2323
  },
  "weather": [
    {
      "id": 800,
      "main": "Clear",
      "description": "clear sky",
      "icon": "01n"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 25.48,
    "feels_like": 26.36,
    "temp_min": 23.86,
    "temp_max": 26.95,
    "pressure": 1011,
    "humidity": 87
  },
  "visibility": 10000,
  "wind": {
    "speed": 3,
    "deg": 140
  },
  "clouds": {
    "all": 0
  },
  "dt": 1695067161,
  "sys": {
    "type": 2,
    "id": 2043475,
    "country": "CN",
    "sunrise": 1695073210,
    "sunset": 1695117382
  },
  "timezone": 28800,
  "id": 1796231,
  "name": "Shanghai Municipality",
  "cod": 200
}
"""


if let data = jsonString.data(using: .utf8) {
    parseWeatherJSON(data: data)
}

  • 这个剂量不起作用

将 JSON 的其中一个键更改为 ,错误是相同的,所以这就是问题所在。namenam

let jsonString = """
{
  ···
  "nam": "Shanghai Municipality",
  ···
}

溶液

  1. 使服务器始终提供正确的格式 JSON,这意味着什么是必须的,什么是可选的。
  2. 将变量从类型设置为nameStringString?