性能优化
用 Swift Codable 解析和生成…
在 Swift 中实现 Codable 模型以编解码 JSON 或属性列表,并处理键映射、日期策略、缺失字段、异构数组与 URLSession/SwiftData/UserDefaults 集成。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
用 Swift Codable 解析和生通用
解决思路
- 按「解码并验证」流程操作:先用代表性的成功、缺失、null、格式错误、缩写键和日期样本进行解码;失败时检查 DecodingError、其 codingPath 和原始负载;只修正不匹配的模型、键、容器或策略,不要用有损解码掩盖契约失败;重新运行样本,并在双向都属于契约时做编解码往返测试。
- 当所有存储属性本身都是 Codable 时,让编译器自动合成 conformance;只读 API 响应用 Decodable,只写用 Encodable,只有双向都需要时才用 Codable。
- 需要重命名 JSON 键时声明 CodingKeys 枚举,无需写自定义解码器;每个存储属性都必须出现在枚举中,省略某属性会将其排除在编解码之外,需提供默认值或单独计算。
- 对合成 conformance 无法处理的转换,重写 init(from:) 和 encode(to:):用 decoder.container(keyedBy:) 取容器,用 container.decode 读取,用 container.decodeIfPresent(...) ?? 默认值 处理缺失键,用 encoder.container(keyedBy:) 和 container.encode 写回。
- 用 nestedContainer(keyedBy:forKey:) 导航并扁平化嵌套 JSON,可链式多次调用以扁平化深层结构;嵌套数组用 nestedUnkeyedContainer(forKey:)。
- 异构数组使用基于 discriminator 的混合数组模式(见 references/codable-advanced-patterns.md#heterogeneous-arrays)。
- 配置 JSONDecoder.dateDecodingStrategy 匹配 API:ISO 8601 用 .iso8601,Unix 秒用 .secondsSince1970,自定义 DateFormatter 用 .formatted(formatter)(设置 dateFormat、locale 为 en_US_POSIX、timeZone 为 GMT),多格式用 .custom 闭包配合 singleValueContainer 解码字符串并尝试多种解析;在 JSONEncoder 上设置匹配的 dateEncodingStrategy。
- 配置数据与键策略:decoder.dataDecodingStrategy = .base64 处理 Base64 Data 字段;decoder.keyDecodingStrategy = .convertFromSnakeCase 处理简单 snake_case 键;encoder 对应设置 .base64 和 .convertToSnakeCase。
- 键策略只用于机械的 snake_case 到 camelCase 映射:convertFromSnakeCase 按拼写匹配,image_url、base_uri、user_id 只匹配 imageUrl、baseUri、userId;若模型用 imageURL、baseURI、userID,必须显式声明 CodingKeys。
- 仅在部分成功属于产品契约时使用有损数组解码(见 references/codable-advanced-patterns.md#lossy-arrays)。
- 用 singleValueContainer() 实现类型安全的原始值包装类型(见 references/codable-advanced-patterns.md#single-value-wrappers)。
- 存储属性的默认值不会让合成解码容忍缺失的非可选键;当契约对缺失或 null 值指定了明确回退行为时,采用缺失键默认值模式(见 references/codable-advanced-patterns.md#missing-key-defaults)。
- 把匹配的编解码策略放在传输/文件格式边界;非规范浮点和属性列表配置见 references/codable-advanced-patterns.md#encoder-configuration。
- 与 URLSession 集成:用 URLSession.shared.data(from:) 获取数据,校验 HTTPURLResponse 状态码在 200...299,配置 JSONDecoder 的 keyDecodingStrategy 和 dateDecodingStrategy 后 decode;泛型 API 信封(如 APIResponse<T>)需在该 helper 内部配置自己的 decoder,因为其他函数的 decoder 不在作用域内。
- 与 SwiftData 集成:保持 schema 值为强类型,持久化设计交给 swiftdata;仅对兼容的非计算模型属性使用 SwiftData(见 references/codable-advanced-patterns.md#persistence-boundaries)。
- 与 UserDefaults 集成:小型偏好用原始类型;小型 Codable 的 RawRepresentable/@AppStorage 交接见 references/codable-advanced-patterns.md#persistence-boundaries;更大或持久数据用真正的持久化层。
- 避免常见错误:缺失默认字段用 decodeIfPresent(...) ?? 默认值 而非 decode;仅在允许部分成功时逐个解码数组元素;设置与 API 格式匹配的 dateDecodingStrategy(默认 .deferredToDate 期望 Double);不要强制解包解码结果,用 guard let;只读响应用 Decodable 而非 Codable;简单 snake_case API 用 keyDecodingStrategy 而非手写 CodingKeys,但缩写拼写仍保留 CodingKeys。
- 按审查清单检查:仅在不需要编码时用 Decodable;可选或缺失键用 decodeIfPresent 加默认值;简单 snake_case API 用 convertFromSnakeCase 且缩写拼写保留 CodingKeys;dateDecodingStrategy 匹配 API 日期格式;不可靠数据数组用有损解码跳过无效元素;自定义 init(from:) 做验证和转换而非解码后修补;JSONEncoder.outputFormatting 包含 .sortedKeys 以获得确定性测试输出;包装类型用 singleValueContainer;用泛型 APIResponse<T> 统一信封处理;不强制解包解码值;持久化边界明确(SwiftData 仅用于兼容的非计算模型属性,@AppStorage/UserDefaults 仅用于小型原始值或 RawRepresentable 偏好)。
适用边界 · 注意事项
- 当只需要解码只读 API 响应时,不要用 Codable(应使用 Decodable),以免不必要地约束类型也必须可编码。
- 不要用有损解码掩盖契约失败;仅当部分成功是产品契约的一部分时才使用有损数组。
- 不要对 imageURL、baseURI、userID 等缩写拼写依赖 convertFromSnakeCase,必须显式声明 CodingKeys。