使用 JSON 解码器读取 json 文件
Using JSON Decoder to read json file
我有一个应用可以获取以下格式的天气 JSON 数据:
{
"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 = ""
}
获取JSON数据的代码如下:
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()
这获取了数据,但我有 2 个问题:
1 - 我正在解码天气描述的数据,但在标签 self.currentWeather.text 中显示时显示
[appName.weatherApiWeather(description: "few clouds")]
而且不仅仅是描述。我该如何解决这个问题?
2 - 我似乎无法访问 JSON 文件密钥 'main' 中保存的数据。如何在结构中设置 'weatherApi' 键以获取 'main' 数据?如果我使用:
struct weatherApi: Codable {
var name:String = ""
var base:String = ""
var weather:[weatherApiMain]
}
struct weatherApiMain: Codable {
var temp: Double
}
我收到一个错误。
I am decoding the data for the weather description but when displaying it in the label self.currentWeather.text
it displays [appName.weatherApiWeather(description: "few clouds")]
and not just the description.
这是因为您正在显示数组的描述:
// currentWeather.weather is an array!
self.lblCurrentWeather.text = currentWeather.weather.description
您应该访问数组中所需元素的描述。比如第一个:
self.lblCurrentWeather.text = currentWeather.weather.first?.description ?? "No Weather!"
我不太了解这个 API 无法告诉您为什么天气数据在数组中。您必须阅读 API 文档才能找到答案。
How do I set up the 'weatherApi' key in a structure to get the 'main' data?
您应该将 属性 命名为 main
而不是 weather
:
struct weatherApi: Codable {
var name:String = ""
var base:String = ""
var main:[weatherApiMain] // notice the change in the name here!
}
auto-generated 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 中有不止一个 main,所以我不确定您需要哪一个。对于第一个,访问权限如上所示:
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。
我有一个应用可以获取以下格式的天气 JSON 数据:
{
"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 = ""
}
获取JSON数据的代码如下:
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()
这获取了数据,但我有 2 个问题:
1 - 我正在解码天气描述的数据,但在标签 self.currentWeather.text 中显示时显示
[appName.weatherApiWeather(description: "few clouds")]
而且不仅仅是描述。我该如何解决这个问题?
2 - 我似乎无法访问 JSON 文件密钥 'main' 中保存的数据。如何在结构中设置 'weatherApi' 键以获取 'main' 数据?如果我使用:
struct weatherApi: Codable {
var name:String = ""
var base:String = ""
var weather:[weatherApiMain]
}
struct weatherApiMain: Codable {
var temp: Double
}
我收到一个错误。
I am decoding the data for the weather description but when displaying it in the label
self.currentWeather.text
it displays[appName.weatherApiWeather(description: "few clouds")]
and not just the description.
这是因为您正在显示数组的描述:
// currentWeather.weather is an array!
self.lblCurrentWeather.text = currentWeather.weather.description
您应该访问数组中所需元素的描述。比如第一个:
self.lblCurrentWeather.text = currentWeather.weather.first?.description ?? "No Weather!"
我不太了解这个 API 无法告诉您为什么天气数据在数组中。您必须阅读 API 文档才能找到答案。
How do I set up the 'weatherApi' key in a structure to get the 'main' data?
您应该将 属性 命名为 main
而不是 weather
:
struct weatherApi: Codable {
var name:String = ""
var base:String = ""
var main:[weatherApiMain] // notice the change in the name here!
}
auto-generated 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 中有不止一个 main,所以我不确定您需要哪一个。对于第一个,访问权限如上所示:
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。