使用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協議有助於減少程式碼並處理序列化和反序列化過程,使程式碼更簡潔易維護。