JSONDecoder 是 Swift 中用于将 JSON 数据解码(解析)成自定义 Swift 类型(如 struct 或 class)的类,属于 Foundation 框架。它是 Swift 的 Codable 系统的一部分,和 JSONEncoder 相对,用于从 JSON 数据生成 Swift 对象。
基础用法
假设有以下 JSON 数据:
{
"name": "Alice",
"age": 30
}
可以定义一个符合 Codable 的 Swift 结构体:
struct Person: Codable {
let name: String
let age: Int
}
然后用 JSONDecoder 来解码:
let jsonData = """
{
"name": "Alice",
"age": 30
}
""".data(using: .utf8)!
do {
let person = try JSONDecoder().decode(Person.self, from: jsonData)
print(person.name) // 输出:Alice
} catch {
print("解码失败:\(error)")
}
关于JSON解码的过程,详细细节可以参考《Swift UI解构JSON文件》或《Swift深入理解Codable协议解码JSON数据》。
功能和配置
JSONDecoder 在 Swift 中提供了多个常见的功能和配置项,可以更灵活地解析 JSON 数据。
1、dateDecodingStrategy(日期解析策略)
处理 JSON 中的时间字符串:
decoder.dateDecodingStrategy = .iso8601 // 解析 "2024-05-07T12:00:00Z"
其他选项包括:
.formatted(DateFormatter) → 自定义 DateFormatter
.secondsSince1970 / .millisecondsSince1970
.custom(…) → 自定义解析闭包
例如解析ISO8601日期,可以参考《Swift使用JSONDecoder解码日期之ISO 8601 标准格式》
2、keyDecodingStrategy(键名转换策略)
decoder.keyDecodingStrategy = .convertFromSnakeCase
举例:
JSON: { “user_name”: “Tom” }
Swift: struct User { let userName: String }
也可自定义映射逻辑:
decoder.keyDecodingStrategy = .custom { codingPath in
let key = codingPath.last!.stringValue
return AnyKey(stringValue: key.uppercased())!
}
在《Swift深入理解Codable协议解码JSON数据》的优化结构体部分,有提及键名转换的实际案例。
3、dataDecodingStrategy(嵌套的二进制数据)
当 JSON 中需要解析的字段是 Base64 编码的字符串(如图片、文件、二进制数据),可以使用这个策略:
decoder.dataDecodingStrategy = .base64
默认情况下,Data 类型会尝试解析 Base64 字符串。如果 JSON 中的数据是 Base64 编码的,就可以用这个配置明确指定:
JSON数据:
{
"file": "SGVsbG8gV29ybGQ=" // 这是 "Hello World" 的 Base64 编码
}
Swift 模型:
struct FileData: Codable {
let file: Data
}
let json = """
{
"file": "SGVsbG8gV29ybGQ="
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
decoder.dataDecodingStrategy = .base64
let fileData = try decoder.decode(FileData.self, from: json)
print(String(data: fileData.file, encoding: .utf8)!) // 输出:Hello World
4、nonConformingFloatDecodingStrategy(处理无效的浮点数)
JSON 标准中不支持 NaN、Infinity、-Infinity 这些浮点数表示。如果服务端返回了这些值,直接解码会失败,可以通过此策略自定义它们的解析。
示例 JSON:
{
"value": "NaN"
}
默认会报错。但是可以设置nonConformingFloatDecodingStrategy解析无效的浮点数:
decoder.nonConformingFloatDecodingStrategy = .convertFromString(
positiveInfinity: "Infinity",
negativeInfinity: "-Infinity",
nan: "NaN"
)
Swift模型:
struct Measurement: Codable {
let value: Double
}
let json = """
{
"value": "NaN"
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
decoder.nonConformingFloatDecodingStrategy = .convertFromString(
positiveInfinity: "Infinity",
negativeInfinity: "-Infinity",
nan: "NaN"
)
let result = try decoder.decode(Measurement.self, from: json)
print(result.value.isNaN) // 输出:true
5、支持嵌套结构、数组、字典解析
struct APIResponse: Codable {
let users: [User]
let metadata: [String: String]
}
嵌套结构可以查看《Swift构建嵌套复杂的JSON的Codable模型结构》一文进行深入理解。
6、容错解码(try? + Optional)
防止解码失败导致整个解析失败:
struct Person: Codable {
let name: String
let age: Int?
}
容错解码部分可以查看《Swift Codable的容错机制:解码不完全匹配的JSON》一文了解相关知识点。
7、解码自定义类型或类型转换(例如字符串转 Int)
需要自定义 init(from decoder: Decoder) 实现类型转换逻辑:
struct Example: Codable {
let id: Int
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let idString = try container.decode(String.self, forKey: .id)
id = Int(idString) ?? 0
}
}
这部分稍微复杂,没有系统的讲解转换逻辑,但是可以在《自定义编码和解码逻辑(SwiftData中实现Codable协议)》一文中了解相关知识点。
核心方法
JSONDecoder().decode(_:from:) 是 Swift 中解码 JSON 数据的核心方法,用于将 JSON 数据(Data 类型)转换成符合 Decodable 协议的 Swift 类型(如 struct 或 class)。
方法定义:
func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable
type: 要解码的目标类型(必须符合 Decodable 协议)
data: JSON 格式的数据,类型是 Data
返回值:目标类型的实例
抛出错误:如果解码失败,会抛出错误,需要用 do-catch 捕捉
示例1:解码JSON对象
import Foundation
struct User: Codable {
let name: String
let age: Int
}
let jsonData = """
{
"name": "Alice",
"age": 25
}
""".data(using: .utf8)!
do {
let user = try JSONDecoder().decode(User.self, from: jsonData)
print(user.name) // 输出:Alice
} catch {
print("解码失败:\(error)")
}
示例2:解码JSON对象数组
let jsonArrayData = """
[
{ "name": "Tom", "age": 22 },
{ "name": "Jerry", "age": 23 }
]
""".data(using: .utf8)!
let users = try JSONDecoder().decode([User].self, from: jsonArrayData)
总结
JSONDecoder().decode(_:from:) 是唯一解码 JSON 数据的方法。但可以通过模型自定义 init(from:)、嵌套容器、解码策略等方式,灵活控制解析过程。
相关文章
1、Swift UI解构JSON文件:https://fangjunyu.com/2024/10/03/swift-ui%e8%a7%a3%e6%9e%84json%e6%96%87%e4%bb%b6/
2、Swift深入理解Codable协议解码JSON数据:https://fangjunyu.com/2025/05/07/swift%e6%b7%b1%e5%85%a5%e7%90%86%e8%a7%a3codable%e5%8d%8f%e8%ae%ae%e8%a7%a3%e7%a0%81json%e6%95%b0%e6%8d%ae/
3、JSONDecoder:https://developer.apple.com/documentation/foundation/jsondecoder
4、Swift使用JSONDecoder解码日期之ISO 8601 标准格式: https://fangjunyu.com/2024/11/11/swift%e4%bd%bf%e7%94%a8-iso-8601-%e6%a0%87%e5%87%86%e6%a0%bc%e5%bc%8f%e6%9d%a5%e8%a7%a3%e6%9e%90%e6%97%a5%e6%9c%9f/
5、Swift Codable的容错机制:解码不完全匹配的JSON:https://fangjunyu.com/2024/12/01/swift-codable%e7%9a%84%e5%ae%b9%e9%94%99%e6%9c%ba%e5%88%b6%ef%bc%9a%e8%a7%a3%e7%a0%81%e4%b8%8d%e5%ae%8c%e5%85%a8%e5%8c%b9%e9%85%8d%e7%9a%84json/
6、自定义编码和解码逻辑(SwiftData中实现Codable协议):https://fangjunyu.com/2024/11/14/%e8%87%aa%e5%ae%9a%e4%b9%89%e7%bc%96%e7%a0%81%e5%92%8c%e8%a7%a3%e7%a0%81%e9%80%bb%e8%be%91%ef%bc%88swiftdata%e4%b8%ad%e5%ae%9e%e7%8e%b0codable%e5%8d%8f%e8%ae%ae%ef%bc%89/
7、Swift UI 深入理解 DecodingError:https://fangjunyu.com/2024/10/05/swift-ui-%e6%b7%b1%e5%85%a5%e4%ba%86%e8%a7%a3decodingerror/
8、Swift构建嵌套复杂的JSON的Codable模型结构:https://fangjunyu.com/2025/05/07/swift%e6%9e%84%e5%bb%ba%e5%b5%8c%e5%a5%97%e5%a4%8d%e6%9d%82%e7%9a%84json%e7%9a%84codable%e6%a8%a1%e5%9e%8b%e7%bb%93%e6%9e%84/