如何使用 JSON.serializer 在 Swift 中解析 JSON
Posted
技术标签:
【中文标题】如何使用 JSON.serializer 在 Swift 中解析 JSON【英文标题】:How to parse JSON in Swift using JSON.serializer 【发布时间】:2020-04-03 18:23:29 【问题描述】:我正在学习在 Xcode 中解析 OpenWeather API 并且有点困惑。 因此,我必须发出 get 请求以接收来自 OpenWeather 的天气报告,然后将其显示在我准备的标签中。
我有带标签网点的主要 VC
class ViewController: UIViewController
@IBOutlet weak var weatherDescriptionlabel: UILabel!
@IBOutlet weak var cityLabel: UILabel!
@IBOutlet weak var currentWeatherLabel: UILabel!
var Data: [DataClass] = []
var cityName: String = ""
var currentWeather: Int = 0
var weatherDescription: String = ""
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
dataLoader().loadData()
我有一个单独的类来“准备”用于传输的 JSON 数据
class WeatherDataClass
let cityName: String
let currentWeather: Int
let weatherDescription: String
init (data: NSDictionary)
let cityName = data["name"] as? String
let currentWeather = data["temp"] as? String
let weatherDescription = data["description"] as? String
self.cityName = cityName!
self.currentWeather = Int(currentWeather!)!
self.weatherDescription = weatherDescription!
还有一个调用 API 的 DataLoader
protocol dataLoaderDelegate
func load( data: [WeatherDataClass] )
class dataLoader
var delegate: dataLoaderDelegate?
var Url = URL(string: "http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=f2a7ca3bd41dfa2efab0ad667aafe1df")!
func loadData()
let url = Url
let request = URLRequest(url: url)
let task = URLSession.shared.dataTask(with: request) data, response, error in
if let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments),
let jsonDict = json as? NSDictionary
var weather: [WeatherDataClass] = []
for (_,data) in jsonDict where data is NSDictionary
if let x = WeatherDataClass(data: data as! NSDictionary)
weather.append(x)
self.delegate?.load(data: weather)
task.resume()
问题是来自 JSONdict 的数据没有包装到 NSDictionary 它仍然是 Any 并给我一个错误
我做错了什么? 提前感谢您的帮助
【问题讨论】:
我建议看看:swiftjson.guide “它仍然是任何并给我错误” - 请分享您遇到的错误。 请搜索。有很多相关问题how to parse openweathermap。并且根本不要在 Swift 中使用NS...
集合类型。您丢弃了导致问题的类型信息。
【参考方案1】:
检查您的请求后,我建议使用JSONDecoder 和Codable 协议。
你应该首先创建你的结构并适应 Codable 协议:
struct Coord: Codable
var lon: Double
var lat: Double
struct Weather: Codable
let id: Int
let icon: String
let main: String
let description: String
struct Main: Codable
let temp: Double
let feelsLike: Double
let tempMin: Double
let tempMax: Double
let pressure: Double
let humidity: Int
struct Wind: Codable
let speed: Int
let deg: Int
struct Clouds: Codable
let all: Int
struct Sys: Codable
let type: Int
let id: Int
let country: String
let sunrise: Int
let sunset: Int
struct WeatherQuery: Codable
let coord: Coord
let weather: [Weather]
let base: String
let main: Main
let visibility: Int
let wind: Wind
let clouds: Clouds
let dt: Int
let sys: Sys
let timezone: Int
let id: Int
let name: String
let cod: Int
完成后,您可以执行以下操作:
let request = URLRequest(url: URL(string: "http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=f2a7ca3bd41dfa2efab0ad667aafe1df")!)
let task = URLSession.shared.dataTask(with: request) data, response, error in
guard let data = data else return
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do
let weatherQuery = try decoder.decode(WeatherQuery.self, from: data)
...
catch
print("[DEBUG] Error is here - \(error)")
task.resume()
【讨论】:
谢谢,这应该有助于理解 Codable 和 Decoder【参考方案2】:看看下面... 以下是来自开放天气 API 的所有数据。随心所欲地定制。
let task = URLSession.shared.dataTask(with: request)
(data, response, error) in
//If data did return and is not nil
if let dataReturned = data
//If let json
if let json = try? JSONSerialization.jsonObject(with: dataReturned, options: .allowFragments) as? NSDictionary
//print("**** WEATHER JSON **** = \(json)")
//Date Formatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
//Picking Apart JSON
let locationName = json["name"] as? String
let visibility = json["visibility"] as? Int
let mainInformation = json["main"] as? NSDictionary
let weatherInArray = json["weather"] as? NSArray
let coords = json["coord"] as? NSDictionary
let system = json["sys"] as? NSDictionary
let wind = json["wind"] as? NSDictionary
let weather = weatherInArray?[0] as? NSDictionary
//Main Information
let temp = mainInformation?.value(forKey: "temp") as? Double
let humidity = mainInformation?.value(forKey: "humidity") as? Int
let pressure = mainInformation?.value(forKey: "pressure") as? Int
let roundedTemp = Int(round(temp ?? 0.00))
//Weather Information
let weatherDiscription = weather?.value(forKey: "description") as? String
let weatherID = weather?.value(forKey: "id") as? Int
//Coords Information
let longitude = coords?.value(forKey: "lon") as? Double
let latitude = coords?.value(forKey: "lat") as? Double
//System Information
let sunrise = system?.value(forKey: "sunrise") as? Int
let sunriseTwo = Double(sunrise ?? 0)
let dateSunrise = NSDate(timeIntervalSince1970: sunriseTwo)
let sunriseTime = dateFormatter.string(from: dateSunrise as Date)
let sunset = system?.value(forKey: "sunset") as? Int
let sunsetTwo = Double(sunset ?? 0)
let dateSunset = NSDate(timeIntervalSince1970: sunsetTwo)
let sunsetTime = dateFormatter.string(from: dateSunset as Date)
//Wind Information
let windSpeed = wind?.value(forKey: "speed") as? Double
let windAngle = wind?.value(forKey: "deg") as? Double
//APPEND TO YOUR ARRAY HERE
Your_Array_Here = Your_Array_here.append(WeatherDataClass(cityName: *** , currentWeather: ***, weatherDescription: *** ))
task.resume()
【讨论】:
以上是关于如何使用 JSON.serializer 在 Swift 中解析 JSON的主要内容,如果未能解决你的问题,请参考以下文章
如何配置 ServiceStack Json Serializer 以将 bool 值写入 int 或 byte?
在ASP.NET MVC中全局应用JSON Serializer设置
ServiceStack Json Serializer 忽略属性