原文:How To Parse JSON in Swift Using Codable and JSONSerialization
在 Swift 中对 JSON、Dictionary 和 Array 进行编码和解码。
这篇文章提供了以下示例代码,用于在不使用第三方依赖包或框架的情况下在 Swift 中对 JSON 编码和解码。
使用 JSONDecoder 将 JSON 解码为 Struct
Decodable
协议允许使用 JSONDecoder
类将 JSON 编码的数据解析为 Swift 结构体。
swift
/// 候选人模型
struct Candidate: Decodable {
var name: String
var skill: String
}
let jsonObject = "{\"name\":\"Taylor\",\"skill\":\"Swift\"}"
let jsonObjectData = jsonObject.data(using: .utf8)!
// 将 json data 解码为 Candidate 结构体
let candidate = try? JSONDecoder().decode(Candidate.self, from: jsonObjectData)
// 访问解码后的 Candidate 结构体属性
candidate?.name // Taylor
candidate?.skill // Swift
⬇️ 代码示例:加载 Bundle 包中的 json 文件,并使用 JSONDecoder 解码为结构体:
swift
import Foundation
// 电影
struct Film: Codable {
let title: String
let year: String
let poster: String
let plot: String
var isExpanded: Bool
// 自定义 init 方法,设置 isExpanded 默认值为 false
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
title = try container.decode(String.self, forKey: .title)
year = try container.decode(String.self, forKey: .year)
poster = try container.decode(String.self, forKey: .poster)
plot = try container.decode(String.self, forKey: .plot)
isExpanded = false
}
}
struct Auteurs: Codable {
let auteurs: [Auteur]
}
// 导演
struct Auteur: Codable {
let name: String
let bio: String
let source: String
let image: String
var films: [Film]
static func auteursFromBundle() -> [Auteur] {
var auteurs: [Auteur] = []
// 加载 Bundle 包中的 auteurs.json 文件,并使用 JSONDecoder 解码。
guard let url = Bundle.main.url(forResource: "auteurs", withExtension: "json") else {
fatalError("Error: Unable to find specified file!")
}
do {
let data = try Data(contentsOf: url)
let json = try JSONDecoder().decode(Auteurs.self, from: data)
auteurs = json.auteurs
} catch {
fatalError("Error occured during parsing, \(error)")
}
return auteurs
}
}
使用 JSONEncoder 将 Struct 编码为 JSON
要将 Swift 结构体编码为 JSON,设置结构体遵守 Codable
协议。
swift
/// 候选人模型
struct Candidate: Codable {
var name: String
var skill: String
}
let candidate = Candidate(
name: "Taylor",
skill: "Swift"
)
// 将 candidate data 编码为 JSON。期待编码后的数据:
// {"name":"Taylor","skill":"Swift"}
let candidateData = try? JSONEncoder().encode(candidate)
将 JSON 数据解析为 Swift Dictionary 和 NSDictionary
在 Swift 中解析 JSON 的另一种方法是使用 JSONSerialization.jsonObject(with:options:)
,它可以解析 JSON 并转换为 Swift Dictionary
和 NSDictionary
。
swift
let jsonDict = "{\"key\":\"value\"}"
let jsonDictData = jsonDict.data(using: .utf8)!
let object = try? JSONSerialization.jsonObject(with: jsonDictData, options: [])
// Cast to a Swift Dictionary
let dict = object as? [AnyHashable:Any]
// Cast to an NSDictionary
let nsDict = object as? NSDictionary
将 JSON 数据解析为 Swift Array 和 NSArray
JSONSerialization.jsonObject(with:options:)
也可用于解析 JSON 并转换为 Swift Array
和 NSArray
。
swift
let jsonArray = "[1,2,3,4,5]"
let jsonArrayData = jsonArray.data(using: .utf8)!
let object = try? JSONSerialization.jsonObject(with: jsonArrayData, options: []) as? [Any]
// Cast to a Swift Array
let array = object as? [Any]
// Cast to a NSArray
let nsArray = object as? NSArray
将 NSDictionary 编码为 JSON
使用 JSONSerialization.data(withJSONObject:options:)
将 NSDictionary
编码为 JSON 数据。
swift
let nsDictionary = NSDictionary(dictionary: [
"key": "value",
"key2": "value2"
])
let nsDictionaryData = try? JSONSerialization.data(withJSONObject: nsDictionary, options: [])
// Expected encoded data:
// {"key":"value","key2":"value2"}
传递 JSONSerialization
写入选项标志 .prettyPrinted
以输出带有缩进和换行格式的 JSON 编码的 NSDictionary
数据。
swift
let prettyNSDictionaryData = try? JSONSerialization.data(
withJSONObject: nsDictionary,
options: [.prettyPrinted]
)
// Expected encoded data:
// {
// "key": "value",
// "key2": "value2"
// }
将 NSArray 编码为 JSON
类似地,可以使用 JSONSerialization.data(withJSONObject:options:)
将 NSArray
编码为 JSON 数据。
swift
let nsArray = NSArray(array: [1,2,3,4,5])
let nsArrayData = try? JSONSerialization.data(
withJSONObject: nsArray,
options: []
)
// Expected encoded data:
// [1,2,3,4,5]
传递 JSONSerialization
写入选项标志 .prettyPrinted
以输出带有缩进和换行格式的 JSON 编码的 NSArray
数据。
swift
let prettyNSArrayData = try? JSONSerialization.data(
withJSONObject: nsArray,
options: [.prettyPrinted]
)
// Expected encoded data:
// [
// 1,
// 2,
// 3,
// 4,
// 5
// ]
为什么不使用 SwiftyJSON 和 Cocoapods 在 Swift 中解析 JSON?
除了 Apple 提供的 JSONSerialization
等类所允许的范围之外,许多应用程序不需要复杂的 JSON 操作。通过使用 Apple 提供的类实现 JSON 解析和编码,开发人员可以:
- 通过删除 SwiftyJSON 等第三方依赖来简化代码库;
- 减少应用程序的二进制包大小;
- 降低与第三方依赖相关的风险;
Swift 中的 JSON 编码和解码
仅此而已!使用 JSONSerialization
、JSONDecoder
和 JSONEncoder
,您可以在 Swift 中使用 JSON,而无需添加任何外部依赖。