Swift JSONDecoder类
Swift JSONDecoder类

Swift JSONDecoder类

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/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注