You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何为单个Encodable类型实现两种编码逻辑以屏蔽敏感字段

两套Encode逻辑实现方案

Swift的Encodable协议默认仅支持单个encode(to:)实现,要实现同类型不同场景的差异化编码,可选择以下两种成熟方案:

方案1:通过userInfo参数控制编码逻辑(侵入性低,推荐小差异场景)

不需要修改原有模型的结构,仅通过给编码器传递自定义标识来控制字段是否编码:

  1. 先定义自定义的编码用户信息键:
extension CodingUserInfoKey {
    /// 标识当前编码是否用于对外分享
    static let isExternalSharing = CodingUserInfoKey(rawValue: "isExternalSharing")!
}
  1. 重写Game类的encode(to:)方法,根据标识判断是否编码lastName:
class Game: Encodable {
    let score: Int
    let firstName: String
    let lastName: String
    
    enum CodingKeys: String, CodingKey {
        case score, firstName, lastName
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        // 两个场景都需要的字段正常编码
        try container.encode(score, forKey: .score)
        try container.encode(firstName, forKey: .firstName)
        
        // 仅本地存储场景编码 lastName
        let isSharing = encoder.userInfo[.isExternalSharing] as? Bool ?? false
        guard !isSharing else { return }
        try container.encode(lastName, forKey: .lastName)
    }
}
  1. 不同场景调用方式:
  • 本地持久化(输出完整JSON):使用默认编码器即可
let localEncoder = JSONEncoder()
let localData = try localEncoder.encode(gameInstance)
  • 对外分享(省略lastName):给编码器传入自定义标识
let shareEncoder = JSONEncoder()
shareEncoder.userInfo[.isExternalSharing] = true
let shareData = try shareEncoder.encode(gameInstance)

方案2:场景化包装类型(逻辑解耦,推荐大差异场景)

如果两个场景的编码规则后续可能有更多差异,可以定义独立的包装类型隔离编码逻辑,原有Game类保持默认实现用于本地存储:

// 原有Game类保持默认Encodable实现,用于本地持久化
class Game: Encodable {
    let score: Int
    let firstName: String
    let lastName: String
    // 原有实现无需修改,用系统自动生成的encode逻辑即可
}

// 对外分享场景专用包装类型
struct ShareableGame: Encodable {
    private let original: Game
    
    enum CodingKeys: String, CodingKey {
        case score, firstName
    }
    
    init(_ game: Game) {
        self.original = game
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(original.score, forKey: .score)
        try container.encode(original.firstName, forKey: .firstName)
    }
}

不同场景调用方式:

  • 本地持久化:直接编码Game实例
  • 对外分享:先包装为ShareableGame再编码
let shareable = ShareableGame(gameInstance)
let shareData = try JSONEncoder().encode(shareable)

内容的提问来源于stack exchange,提问作者Will

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:45:05