使用外键时Supabase Swift解码失败问题排查
Supabase Swift SDK 关联外键查询解码失败:期望Dictionary<String, Any>却得到字符串
使用Supabase Swift SDK查询关联外键表时,调用.select("*, account(*)")会触发解码错误,提示“Expected to decode Dictionary<String, Any> but found a string instead”。但如果逐个指定所有字段(而非使用*通配符),查询就能正常解码。
复现信息
模型定义
struct Transaction: Codable { var id: UUID var name: String var subtitle: String? var merchant: String? var amount: Decimal var tax_deductible: Bool = false var date: Date var account: TransactionAccount? } enum AccountType: String, Codable, CaseIterable { case debit case savings case loan case credit case cash } struct TransactionAccount: Codable, Hashable { var id: UUID var name: String var description: String? var type: AccountType var color: String }
SDK查询代码
do { return try await Database.shared .client .database .from("transactions") .select("*, account(*)") .in("type", value: scope.transactionTypes.map({ $0.rawValue })) .execute() .value } catch { return [] }
解码错误详情
Printing description of error: ▿ DecodingError ▿ typeMismatch : 2 elements - .0 : Swift.Dictionary<Swift.String, Any> ▿ .1 : Context ▿ codingPath : 2 elements ▿ 0 : _JSONKey(stringValue: "Index 2", intValue: 2) ▿ rep : Rep - index : 2 - 1 : CodingKeys(stringValue: "account", intValue: nil) - debugDescription : "Expected to decode Dictionary<String, Any> but found a string instead." - underlyingError : nil
问题原因
使用*通配符会返回transactions表的所有字段,其中包含原始的外键字段(account,类型为字符串UUID),而.select("account(*)")又尝试将该外键扩展为关联的TransactionAccount对象。此时返回的JSON中,account字段可能因Supabase处理逻辑冲突,部分条目返回原始外键值而非关联对象,导致Codable解码器无法匹配预期的TransactionAccount类型。
解决方案
明确指定查询字段(推荐)
放弃使用*通配符,逐个列出transactions表的所有字段及关联对象的字段,确保返回的account仅为关联对象:.select("id, name, subtitle, merchant, amount, tax_deductible, date, account(*)")此方法已验证可行,能彻底避免原始外键字段与扩展对象的冲突。
排除原始外键字段
若需保留*通配符,可通过Supabase的字段排除语法去掉原始外键字段(假设外键列名为account):.select("*, !account, account(*)")该语法会先返回所有字段,再排除原始的
account外键字段,最后返回扩展后的account对象。检查数据与权限
- 确认数据库中所有
transactions表的account外键均存在对应的transaction_accounts表记录,避免因关联缺失导致返回原始外键值。 - 检查Supabase的RLS(行级安全)策略,确保当前用户有权限访问
transaction_accounts表的所有字段,权限不足可能导致关联对象无法正常返回, fallback到原始外键值。
- 确认数据库中所有
内容的提问来源于stack exchange,提问作者Brandon Stillitano
相关产品推荐
相关产品推荐

