Swift 读取JSON文件
在这篇文章中,我们将看到一些例子,说明我们如何使用JSONSerialization和JSONDecoder类读取JSON文件。现在,这些类在大多数iOS应用程序中被用来处理JSON文件。
你可以使用JSONSerialization类来读取Swift语言中的JSON文件。为了读取json文件,首先你需要将其转换为一个字符串或数据对象。之后,你可以将字符串或数据对象传递给JSONserialization类,将其转换为字典或数组对象。
JSONSerialization
iOS和macOS的Foundation框架默认包括一个JSONserialization类。要创建一个Swift字典或数组,这个类需要一个字符串或数据对象。使用同一个类,你也可以把一个字典或数组变成一个JSON对象。序列化和反序列化程序由JSONerialization类处理。
这个类的主要函数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中,苹果引入了Codable协议,使序列化和反序列化过程变得简单。这个协议提供了一种灵活的方式来使用JSON数据来解析和存储数据到模型类/结构。该协议可用于将模型对象轻松转换为JSON数据。
Codable协议有助于减少代码,处理序列化和反序列化的过程,使代码更加简洁和可维护。