Swift多态序列化:如何访问枚举Node关联的Pull/Issue对象
解决GitHub GraphQL多态Codable枚举访问关联对象的问题
常见原因及解决步骤
检查枚举关联值的类型匹配与解码逻辑
先确认你的Node枚举自定义解码逻辑中,__typename的判断和关联值类型完全对应。GitHub GraphQL返回的__typename固定是"Issue"和"PullRequest",别出现拼写错误。示例正确实现:enum Node: Codable { case issue(IssueDTO) case pullRequest(PullRequestDTO) private enum CodingKeys: String, CodingKey { case __typename } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let typeName = try container.decode(String.self, forKey: .__typename) switch typeName { case "Issue": let issue = try IssueDTO(from: decoder) self = .issue(issue) case "PullRequest": let pr = try PullRequestDTO(from: decoder) self = .pullRequest(pr) default: throw DecodingError.dataCorruptedError(forKey: .__typename, in: container, debugDescription: "Unsupported node type: \(typeName)") } } }注意:解码DTO时要直接用
decoder而非子容器,因为Issue/PR的字段和__typename处于同一层级。禁止直接强制转换枚举实例
不要尝试把Node枚举实例直接as? IssueDTO——枚举是独立类型,关联值是包裹在case里的,必须通过switch或if case提取:
错误写法:let issue = node as? IssueDTO // 必然失败正确写法:
switch node { case .issue(let issue): // 正常访问issue的所有属性 print(issue.title) case .pullRequest(let pr): print(pr.headRefName) }或者用条件绑定:
if case .issue(let issue) = node { // 处理issue }排查DTO的Codable实现隐患
虽然整体序列化无报错,但单个DTO可能存在隐藏问题(比如非可选字段实际返回nil,但通过默认值绕过了解码错误)。可以单独截取一个Issue/PR的JSON片段,直接解码对应的DTO,验证属性是否正常初始化:let testIssueJSON = """ { "__typename": "Issue", "title": "Test Issue", "number": 123 } """.data(using: .utf8)! let testIssue = try JSONDecoder().decode(IssueDTO.self, from: testIssueJSON) print(testIssue.title) // 确认输出正常验证解码时的类型匹配
在Node的init(from:)方法中添加打印,确认__typename和解码后的DTO实例是否匹配:init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let typeName = try container.decode(String.self, forKey: .__typename) print("Decoding node type: \(typeName)") switch typeName { case "Issue": let issue = try IssueDTO(from: decoder) print("Decoded issue: \(issue)") self = .issue(issue) // ... 其他case } }确保打印的类型和实际解码的DTO一致,避免出现把PullRequest解码到Issue case的情况。
内容的提问来源于stack exchange,提问作者streetturtle
相关产品推荐
相关产品推荐

