使用Swift读取JSON文件
在本文中,我们将了解一些使用JSONSerialization和JSONDecoder类读取JSON文件的示例。如今,大多数iOS应用程序都使用这些类来处理JSON文件。
您可以使用JSONSerialization类在Swift语言中读取JSON文件。为了读取json文件,首先需要将其转换为字符串或数据对象。之后,您可以将字符串或数据对象传递给JSONSerialization类,将其转换为字典或数组对象。
JSONSerialization
iOS和macOS的Foundation框架默认包含JSONSerialization类。要创建Swift字典或数组,此类需要字符串或数据对象。使用相同的类,您还可以将字典或数组转换为JSON对象。JSONSerialization类处理序列化和反序列化过程。
此类的主要函数jsonObject(with:options:)用于反序列化,或将JSON数据转换为Swift对象。此方法需要一个包含JSON数据的数据对象,以及一个名为options的参数,该参数控制方法的行为。此方法返回一个Swift对象,该对象可以是数组或字典。JSON数据格式将决定返回类型。
以下是如何读取JSON文件并将其解析为字典的示例:
使用JSONSerialization类读取JSON
这是一个JSON示例:
示例
{ "id": 1, "title": "iPhone 12", "price": 749, "thumbnail": "https://i.dummyjson.com/data/products/1/thumbnail.jpg", "manufacturedDetail": { "company": { "manufacturedBy": "Apple Inc." } } }
我们将使用上面的JSON来读取它。您可以通过为文件命名,向Xcode项目添加一个扩展名为“.json”的新文件。
读取JSON文件
func readJSONFile(forName name: String) { do { if let bundlePath = Bundle.main.path(forResource: name, ofType: "json"), let jsonData = try String(contentsOfFile: bundlePath).data(using: .utf8) { if let json = try JSONSerialization.jsonObject(with: jsonData, options: .mutableLeaves) as? [String: Any] { print("JSON: \(json)") } else { print("Given JSON is not a valid dictionary object.") } } } catch { print(error) } }
输出
JSON: ["title": iPhone 12, "price": 749, "thumbnail": https://i.dummyjson.com/data/products/1/thumbnail.jpg, "id": 1, "manufacturedDetail": { company = { manufacturedBy = "Apple Inc."; }; }]
这将为您提供一个JSON对象,您可以在代码中将其用作字典。如果您的JSON文件是对象的数组,则可以使用mutableContainers选项而不是mutableLeaves。由于我们必须从JSON对象读取字典,因此我们将使用mutableLeaves选项。
使用JSONDecoder()类读取JSON
Swift的新版本引入了Codable协议,这使得使用起来更加容易和灵活。
然后使用JSONDecoder类将文件中的JSON数据解析为给定类型的实例(类或结构)。decode(_:from:)方法用于反序列化JSON数据,然后返回生成的Type对象以访问Type对象的属性。
我们正在尝试使用Codable协议读取上面给出的相同JSON作为示例。在我们准备好使用JSONDecoder()类解码JSON数据之前,让我们准备在解码时提供的模型类。
根据上面的JSON数据,这是模型类:
import Foundation struct Product: Decodable { let id: Int let title: String let price: Int let thumbnail: String let manufacturedBy: String enum RootKeys: String, CodingKey { case id, title, price, thumbnail, manufacturedDetail } enum ManufacturedKeys: String, CodingKey { case company } enum CompanyKeys: String, CodingKey { case manufacturedBy } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: RootKeys.self) id = try values.decode(Int.self, forKey: .id) title = try values.decode(String.self, forKey: .title) price = try values.decode(Int.self, forKey: .price) thumbnail = try values.decode(String.self, forKey: .thumbnail) let manufacturedContainer = try values.nestedContainer(keyedBy: ManufacturedKeys.self, forKey: .manufacturedDetail) let companyContainer = try manufacturedContainer.nestedContainer(keyedBy: CompanyKeys.self, forKey: .company) self.manufacturedBy = try companyContainer.decode(String.self, forKey: .manufacturedBy) } }
如何解码?
func readJSONFile(forName name: String) { do { // creating a path from the main bundle and getting data object from the path if let bundlePath = Bundle.main.path(forResource: name, ofType: "json"), let jsonData = try String(contentsOfFile: bundlePath).data(using: .utf8) { // Decoding the Product type from JSON data using JSONDecoder() class. let product = try JSONDecoder().decode(Product.self, from: jsonData) print("Product name: \(product.title) and its price: \(product.price)") } } catch { print(error) } }
输出
Product name: iPhone 12 and its price: 749
结论
在Swift中,您可以通过低级API将原始JSON数据转换为数组或字典之类的集合。您可以使用JSONSerialization类将原始JSON对象转换为有意义的对象。此类内置于Foundation框架中。您可以在任何平台(例如iOS、macOS、watchOS等)上使用此类。此外,反过来,您可以使用反序列化过程将自定义对象转换回原始JSON数据。
在Swift 4中,Apple引入了Codable协议,该协议使序列化和反序列化过程变得容易。此协议提供了一种灵活的方式来使用JSON数据来解析数据并将其存储到模型类/结构中。此协议可用于轻松地将模型对象转换为JSON数据。
Codable协议有助于减少代码并处理序列化和反序列化过程,使代码更简洁易维护。