Swift中如何处理值类型动态变化的JSON解码?
适配多类型data字段的Swift Codable实现
针对后端返回的data字段存在三种类型的情况,我们可以通过自定义遵循Decodable协议的枚举来处理,无需修改后端逻辑。
步骤1:定义自定义枚举处理多类型解码
创建枚举RegistrationData,枚举成员对应三种返回情况,并在init(from:)方法中依次尝试解码不同类型:
enum RegistrationData: Decodable { case success(Bool) case singleError(String) case multipleErrors([String]) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() // 优先尝试解码布尔值(注册成功场景) if let successFlag = try? container.decode(Bool.self) { self = .success(successFlag) return } // 尝试解码单个字符串(单条错误原因场景) if let singleErr = try? container.decode(String.self) { self = .singleError(singleErr) return } // 最后尝试解码字符串数组(多条错误原因场景) if let multiErrs = try? container.decode([String].self) { self = .multipleErrors(multiErrs) return } // 所有类型都不匹配时抛出解码错误 throw DecodingError.dataCorruptedError( in: container, debugDescription: "无法识别的data字段类型" ) } }
步骤2:定义注册响应结构体
创建包含后端返回字段的结构体,其中data字段使用上面定义的RegistrationData类型:
struct RegistrationResponse: Decodable { let code: Int // 后端状态码,比如200=成功,400=失败 let message: String? // 可选的全局提示信息 let data: RegistrationData }
步骤3:解码与结果处理
通过JSONDecoder解码响应数据后,使用switch语句处理不同的返回情况:
// 示例:解码不同场景的JSON响应 func handleRegistrationResponse(jsonStr: String) { guard let jsonData = jsonStr.data(using: .utf8) else { print("无效的JSON字符串") return } do { let response = try JSONDecoder().decode(RegistrationResponse.self, from: jsonData) switch response.data { case .success(let isSuccess): print("注册成功:\(isSuccess)") case .singleError(let errMsg): print("注册失败:\(errMsg)") case .multipleErrors(let errList): print("注册失败,原因:\(errList.joined(separator: ";"))") } } catch { print("解码失败:\(error.localizedDescription)") } } // 测试不同场景 let successJson = """ {"code":200,"message":"注册成功","data":true} """ handleRegistrationResponse(jsonStr: successJson) let singleErrJson = """ {"code":400,"message":"注册失败","data":"用户名已存在"} """ handleRegistrationResponse(jsonStr: singleErrJson) let multiErrJson = """ {"code":400,"message":"注册失败","data":["用户名已存在","密码长度不足6位"]} """ handleRegistrationResponse(jsonStr: multiErrJson)
补充说明
- 如果需要将数据编码回JSON(比如调试时),可以让
RegistrationData遵循Codable并实现encode(to:)方法:extension RegistrationData: Encodable { func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .success(let flag): try container.encode(flag) case .singleError(let msg): try container.encode(msg) case .multipleErrors(let list): try container.encode(list) } } } - 解码顺序可以根据后端返回的优先级调整,确保最常见的场景优先尝试,提升解码效率。
内容的提问来源于stack exchange,提问作者swifthing
相关产品推荐
相关产品推荐

