Swift解码JSON时如何自动解密SHA-256加密的URL字段?
解决方案:自定义Codable解码逻辑自动解密URL
当然可以实现!核心思路是重写TableCellData的自定义解码初始化器,在解码url字段的环节直接调用你的SHA-256解密函数,把加密后的字符串解密后再转换成URL类型。这样整个解码流程完成后,url属性就已经是可用的正常URL,完全不需要在后续使用时再额外处理。
步骤1:先定义你的解密函数
假设你已经有一个处理SHA-256解密的函数,示例如下(你需要替换成自己的实际解密逻辑):
func decryptSHA256(_ encryptedString: String) -> String? { // 这里编写你的SHA-256解密逻辑,返回解密后的原始URL字符串 // 举个模拟例子:假设加密前缀是"sha256_",解密时移除该前缀 return encryptedString.replacingOccurrences(of: "sha256_", with: "") }
步骤2:重写TableCellData的解码初始化器
修改你的TableCellData结构体,添加自定义的init(from decoder: Decoder)方法,在解码url字段时插入解密逻辑:
struct TableCellData: Codable { let type: Int let cellText: String let cellImage: String? let url: URL? let detailText: String? let tableID: Int? enum CodingKeys: String, CodingKey { case type = "type" case cellText = "cell_text" case cellImage = "cell_image" case url = "url" case detailText = "detail_text" case tableID = "table_id" } // 自定义解码初始化器,替换默认的自动解码逻辑 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 先解码不需要特殊处理的字段 type = try container.decode(Int.self, forKey: .type) cellText = try container.decode(String.self, forKey: .cellText) cellImage = try container.decodeIfPresent(String.self, forKey: .cellImage) detailText = try container.decodeIfPresent(String.self, forKey: .detailText) tableID = try container.decodeIfPresent(Int.self, forKey: .tableID) // 处理url字段:解码加密字符串 → 解密 → 转换为URL if let encryptedUrlString = try container.decodeIfPresent(String.self, forKey: .url) { if let decryptedUrlString = decryptSHA256(encryptedUrlString) { url = URL(string: decryptedUrlString) } else { // 解密失败时,将url设为nil(也可根据需求抛出解码错误) url = nil } } else { // 接口返回url字段为null时,直接设为nil url = nil } } } // 保留你原有的扩展代码无需修改 extension TableCellData { init?(data: Data) { guard let me = try? JSONDecoder().decode(TableCellData.self, from: data) else { return nil } self = me } init?(_ json: String, using encoding: String.Encoding = .utf8) { guard let data = json.data(using: encoding) else { return nil } self.init(data: data) } init?(fromURL url: String) { guard let url = URL(string: url) else { return nil } guard let data = try? Data(contentsOf: url) else { return nil } self.init(data: data) } var jsonData: Data? { return try? JSONEncoder().encode(self) } var json: String? { guard let data = self.jsonData else { return nil } return String(data: data, encoding: .utf8) } }
为什么这样可行?
当你调用JSONDecoder().decode(TableCellData.self, from: data)时,解码器会自动使用我们自定义的init(from decoder: Decoder)方法,而非默认的自动解码逻辑。这样我们就能在解码url字段的流程中,无缝插入解密步骤,确保最终的url属性是解密后的可用URL。
额外说明
- 如果解密失败或者解密后的字符串无法转换成
URL,上面的代码会把url设为nil,你也可以根据业务需求改成抛出解码错误(比如throw DecodingError.dataCorrupted(...))。 - 你原有的扩展代码不需要做任何修改,因为
init?(data: Data)依然依赖JSONDecoder,而解码器现在会自动使用我们的自定义解码逻辑。
内容的提问来源于stack exchange,提问作者Mr Some Dev.
相关产品推荐
相关产品推荐

