iOS Swift JSON解析教程
在本教程中,我们将学习如何使用Swift在我们的iOS应用程序中解析JSON响应。
我们将在UITableView中显示已解析的响应。
要了解有关UITableView的更多信息,请先阅读本教程,然后再继续。
Swift JSON解析
JSON是最常用的从Web服务发送和接收数据的格式。
数据采用键值对的形式。
使用Swift字典,我们可以轻松地从键中获取值。
在本教程中,我们将解析本地资源文件中的JSON数据。
JSONSerialization类用于通过转换Data对象将JSON数据解析为键值对字典。
JSON数据的类型为[String:Any]。
让我们创建一个单视图iOS应用程序,其中将本地创建的JSON文件中的数据解析到TableView中。
iOS JSON解析示例项目结构
在Main.storyboard中,我们向ViewController添加了标签和TableView。
我们已经将TableView委托设置为ViewController。
有关如何使用Storyboard设置TableView的更多信息,请参考本教程。
Swift JSON解析代码
我们将从文件中解析JSON数据。response.json文件如下所示:
序列化数据
let url = Bundle.main.url(forResource: "response", withExtension: "json")
guard let jsonData = url else{return}
guard let data = try? Data(contentsOf: jsonData) else { return }
guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else{return}
在上面的代码中,我们通过Bundle.main.url实例获取文件。
Data实例将其转换为Data格式,然后将其序列化为JSON。
从JSON实例获取数据
现在我们有了JSON实例,我们可以通过以下方式获取数据:
if let dictionary = json as? [String: Any] {
if let title = dictionary["title"] as? String {
labelHeader.text = title
}
if let year = dictionary["year"] as? Double {
print("Year is \(year)")
}
if let more_info = dictionary["more_info"] as? Double {
//This doesn't get printed.
print("More_info is \(more_info)")
}
for (key, value) in dictionary {
print("Key is: \(key) and value is \(value)" )
}
}
在TableView中,我们将填充另一个JSON文件:
ViewController.swift
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var labelHeader: UILabel!
@IBOutlet weak var tableView: UITableView!
var movieList = [MarvelData]()
override func viewDidLoad() {
super.viewDidLoad()
//Do any additional setup after loading the view, typically from a nib.
let url = Bundle.main.url(forResource: "response", withExtension: "json")
guard let jsonData = url
else{
print("data not found")
return
}
guard let data = try? Data(contentsOf: jsonData) else { return }
guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else{return}
if let dictionary = json as? [String: Any] {
if let title = dictionary["title"] as? String {
labelHeader.text = title
}
if let year = dictionary["year"] as? Double {
print("Year is \(year)")
}
if let more_info = dictionary["more_info"] as? Double {
//This doesn't get printed.
print("More_info is \(more_info)")
}
for (key, value) in dictionary {
print("Key is: \(key) and value is \(value)" )
}
}
//Now lets populate our TableView
let newUrl = Bundle.main.url(forResource: "marvel", withExtension: "json")
guard let j = newUrl
else{
print("data not found")
return
}
guard let d = try? Data(contentsOf: j)
else { print("failed")
return
}
guard let rootJSON = try? JSONSerialization.jsonObject(with: d, options: [])
else{ print("failedh")
return
}
if let JSON = rootJSON as? [String: Any] {
labelHeader.text = JSON["title"] as? String
guard let jsonArray = JSON["movies"] as? [[String: Any]] else {
return
}
print(jsonArray)
let name = jsonArray[0]["name"] as? String
print(name ?? "NA")
print(jsonArray.last!["year"] as? Int ?? 1970)
for json in jsonArray
{
guard let movieName = json["name"] as? String else{ return }
guard let movieYear = json["year"] as? Int else{ return }
movieList.append(MarvelData(movieName: movieName, movieYear: movieYear))
}
self.tableView.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movieList.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let currentMovie = movieList[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
cell.textLabel?.text = currentMovie.movieName
cell.detailTextLabel?.text = "\(currentMovie.movieYear)"
return cell
}
}
struct MarvelData {
let movieName: String
let movieYear: Int
public init(movieName: String, movieYear: Int) {
self.movieName = movieName
self.movieYear = movieYear
}
}
在上面的代码中,我们还解析了第二个json文件,并将每个JSON Array元素追加到保存结构的数组中。
为了显示这些数据,我们必须在tableView实例上调用reloadData()。
我们可以使在结构实例中设置json值的代码更好。
struct MarvelData {
var movieName: String
var movieYear: Int
init(_ dictionary: [String: Any]) {
self.movieName = dictionary["name"] as? String ?? "NA"
self.movieYear = dictionary["year"] as? Int ?? 1970
}
}
这样做我们可以更改:
guard let movieName = json["name"] as? String else{ return }
guard let movieYear = json["year"] as? Int else{ return }
movieList.append(MarvelData(movieName: movieName, movieYear: movieYear))
至
movieList.append(MarvelData(json))
无需使用for循环遍历jsonArray,我们可以轻松地在Swift中使用方便的运算符concatMap。
所以这:
for json in jsonArray
{
movieList.append(MarvelData(json))
}
更改为
movieList = jsonArray.compactMap{return MarvelData(##代码##)}
//or
movieList = jsonArray.compactMap{MarvelData(##代码##)}
//or
movieList = jsonArray.compactMap(MarvelData.init)

