Swift中如何为单个Encodable类型实现两种编码逻辑以屏蔽敏感字段
两套Encode逻辑实现方案
Swift的Encodable协议默认仅支持单个encode(to:)实现,要实现同类型不同场景的差异化编码,可选择以下两种成熟方案:
方案1:通过userInfo参数控制编码逻辑(侵入性低,推荐小差异场景)
不需要修改原有模型的结构,仅通过给编码器传递自定义标识来控制字段是否编码:
- 先定义自定义的编码用户信息键:
extension CodingUserInfoKey { /// 标识当前编码是否用于对外分享 static let isExternalSharing = CodingUserInfoKey(rawValue: "isExternalSharing")! }
- 重写
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) } }
- 不同场景调用方式:
- 本地持久化(输出完整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
相关产品推荐
相关产品推荐

