0Pricing
Swift Academy · 课时

键与日期解码策略

使用 snake_case 和日期解码策略。

键与日期解码策略 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。

解码策略概览

您不必为每种类型都编写一个 CodingKeys 枚举,也可以在解码器上设置全局策略。策略会统一转换键,并在所有解码类型中以一致的方式解析日期。

import Foundation

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
print("Strategy configured")

convertFromSnakeCase

设置 keyDecodingStrategy = .convertFromSnakeCase 后,会自动将类似 first_name 的键映射到 camelCase 属性 firstName,无需使用 CodingKeys。

import Foundation

struct User: Codable {
    var firstName: String
    var lastName: String
}

let json = "{\"first_name\":\"Ada\",\"last_name\":\"Lovelace\"}"
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let u = try decoder.decode(User.self, from: json.data(using: .utf8)!)
print(u.firstName, u.lastName)

编码为蛇形命名法

编码器也有对应的选项:keyEncodingStrategy = .convertToSnakeCase 会将 camelCase 属性写出为 snake_case JSON 键。

import Foundation

struct User: Codable {
    var firstName: String
}

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let data = try encoder.encode(User(firstName: "Ada"))
print(String(data: data, encoding: .utf8)!)

策略应用于所有键

键策略会统一应用于每种嵌套类型的每个属性。当整个 API 都一致使用 snake_case 时,这种方式非常理想。

import Foundation

struct Meta: Codable { var createdAt: String }
struct Doc: Codable { var docTitle: String; var docMeta: Meta }

let json = "{\"doc_title\":\"A\",\"doc_meta\":{\"created_at\":\"now\"}}"
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let d = try decoder.decode(Doc.self, from: json.data(using: .utf8)!)
print(d.docTitle, d.docMeta.createdAt)

日期问题

JSON 没有日期类型。Date 值会被编码为数字或字符串,解码器需要知道具体格式。dateDecodingStrategy 会告诉它应如何解析。

import Foundation

struct Event: Codable {
    var name: String
    var date: Date
}

print("Date needs a strategy to parse")

iso8601 日期解码

dateDecodingStrategy = .iso8601 会将类似 2020-01-01T00:00:00Z 的标准 ISO-8601 时间戳解析为 Date 值。

import Foundation

struct Event: Codable {
    var name: String
    var date: Date
}

let json = "{\"name\":\"Launch\",\"date\":\"2020-01-01T00:00:00Z\"}"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let e = try decoder.decode(Event.self, from: json.data(using: .utf8)!)
print(e.date.timeIntervalSince1970)

iso8601 日期编码

编码器对应的选项是 dateEncodingStrategy = .iso8601,它会将 Date 值写成 ISO-8601 字符串。

import Foundation

struct Event: Codable {
    var name: String
    var date: Date
}

let e = Event(name: "Launch", date: Date(timeIntervalSince1970: 1577836800))
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
let data = try encoder.encode(e)
print(String(data: data, encoding: .utf8)!)

secondsSince1970 策略

当 API 以数字发送 Unix 时间戳时,请使用 .secondsSince1970 将其解释为自纪元以来经过的秒数。

import Foundation

struct Event: Codable {
    var date: Date
}

let json = "{\"date\":1577836800}"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
let e = try decoder.decode(Event.self, from: json.data(using: .utf8)!)
print(e.date.timeIntervalSince1970)

自定义日期格式

对于非标准格式,请通过 .formatted(_:) 提供一个 DateFormatter。这样可以处理类似 2020-01-01 这种不包含时间部分的日期。

import Foundation

struct Event: Codable { var date: Date }

let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd"
fmt.timeZone = TimeZone(identifier: "UTC")
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(fmt)
let e = try decoder.decode(Event.self, from: "{\"date\":\"2020-01-01\"}".data(using: .utf8)!)
print(e.date.timeIntervalSince1970)

组合使用策略

您可以在同一个解码器上同时设置键策略和日期策略,从而处理使用 snake_case 且采用 ISO-8601 格式的 API,无需为每种类型编写额外样板代码。

import Foundation

struct LogEntry: Codable {
    var eventName: String
    var occurredAt: Date
}

let json = "{\"event_name\":\"login\",\"occurred_at\":\"2020-01-01T00:00:00Z\"}"
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .iso8601
let entry = try decoder.decode(LogEntry.self, from: json.data(using: .utf8)!)
print(entry.eventName, entry.occurredAt.timeIntervalSince1970)

策略与 CodingKeys

对于格式统一的 API,全局策略更加简洁。当只有少数键不同或名称不规则时,显式的 CodingKeys 枚举可以对每个键进行精确控制。两种方式甚至可以结合使用。

import Foundation

struct Item: Codable {
    var itemName: String
}

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let i = try decoder.decode(Item.self, from: "{\"item_name\":\"Pen\"}".data(using: .utf8)!)
print(i.itemName)

快速检查:策略

检验您对解码策略的理解。

回顾:键策略与日期策略

您学习了如何配置全局编码器:

  • keyDecodingStrategy = .convertFromSnakeCase 会将 snake_case 映射为 camelCase;.convertToSnakeCase 则以相反方向进行编码。
  • dateDecodingStrategy = .iso8601 会解析 ISO 时间戳;.secondsSince1970 和 .formatted(_:) 可处理其他格式。
  • 策略会统一应用于每种嵌套类型。
  • 对于格式统一的 API,请使用策略;对于不规则的 API,请使用 CodingKeys。

常见问题解答

「键与日期解码策略」课时是免费的吗?

是的 — 「键与日期解码策略」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。

「键与日期解码策略」这节课中我会学到什么?

使用 snake_case 和日期解码策略。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Swift Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「键与日期解码策略」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Swift Academy 课中编写并运行代码吗?

能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 CodingKeys 重命名
  2. 键与日期解码策略
  3. 手动实现 encode(to:) 与 init(from:)
  4. 解码异构 JSON
← 返回 Swift Academy