问题描述
{
"coord":{
"lon":-1.74,"lat":60.5
},"weather":[
{
"id":801,"main":"Clouds","description":"few clouds","icon":"02n"
}
],"main":{
"temp":285.17,"feels_like":275.99,"temp_min":285.17,"temp_max":285.17
},"timezone":3600,"id":2654970,"name":"Brae","cod":200
}
我已经设置了Codable结构,如下所示:
struct weatherApi: Codable {
var name:String = ""
var base:String = ""
var weather:[weatherApiWeather]
}
struct weatherApiWeather: Codable {
var description: String = ""
}
let dataTask = session.dataTask(with: url!) {(data,response,error) in
if error == nil && data != nil {
let decoder = JSONDecoder()
do {
let currentWeather = try decoder.decode(weatherApi.self,from: data!)
dispatchQueue.main.async {
self.lblCurrentWeather.text = currentWeather.weather.description //UILabel
}
}
catch {
print ("Error parsing Json")
}
}
}
dataTask.resume()
1-我正在解码用于天气描述的数据,但是当在标签self.currentWeather.text中显示时会显示
[appName.weatherApiWeather(description: "few clouds")]
,而不仅仅是说明。我该如何解决?
2-我似乎无法访问JSON文件密钥“ main”中保存的数据。如何在结构中设置“ weatherApi”键以获取“主要”数据?如果我使用:
struct weatherApi: Codable {
var name:String = ""
var base:String = ""
var weather:[weatherApiMain]
}
struct weatherApiMain: Codable {
var temp: Double
}
解决方法
我正在解码用于天气描述的数据,但是当在标签
self.currentWeather.text
中显示数据时,它将显示[appName.weatherApiWeather(description: "few clouds")]
不仅是描述。
这是因为您正在显示数组的描述:
// currentWeather.weather is an array!
self.lblCurrentWeather.text = currentWeather.weather.description
您应该改为访问数组所需元素的描述。例如,第一个:
self.lblCurrentWeather.text = currentWeather.weather.first?.description ?? "No Weather!"
我对该API知之甚少,无法告诉您为什么天气数据位于数组中。您必须阅读API文档才能找到答案。
如何在结构中设置“ weatherApi”键以获取“主要”数据?
您应该将属性命名为main
,而不是weather
:
struct weatherApi: Codable {
var name:String = ""
var base:String = ""
var main:[weatherApiMain] // notice the change in the name here!
}
自动生成的Codable
实现将使用属性名称作为JSON密钥。如果需要,您仍然可以使用weather
,但是必须添加一个CodingKeys
枚举:
struct weatherApi: Codable {
var name:String = ""
var base:String = ""
var weather:[weatherApiMain]
enum CodingKeys: String,CodingKey {
case name = "name"
case base = "base"
case weather = "main"
}
}
,
第一个问题- 由于天气是一个数组,因此此行要求提供数组的描述,看来:
self.lblCurrentWeather.text = currentWeather.weather.description
要获得描述,应标识数组中的特定元素,如下所示:
self.lblCurrentWeather.text = currentWeather.weather[0].description
第二个问题-
上面的JSON中有多个主要版本,因此我不确定您需要哪个。对于第一个,访问将类似于上面:
anotherLabel.text = currentWeather.weather[0].main
对于其他主要模型,需要更新模型:
struct weatherApi: Codable {
let main:Main
var name:String = ""
var base:String = ""
var weather:[weatherApiMain]
}
struct Main: Codable {
let temp: Double
}
然后访问main的内容是这样的:
yetAnotherLabel.text = currentWeather.main.temp
此外,可以将模型的每个属性分配为let而不是var。