You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中上传Codable结构体至Firebase实时数据库报错求助

解决Firebase实时数据库上传Codable结构体的错误问题

错误原因

你遇到的InvalidFirebaseData错误,是因为Firebase实时数据库仅支持存储基础类型(字符串、数字)、数组和字典,而你直接将自定义的PrintifyLineItems、PrintifyAddress结构体对象放入values字典中——Swift自定义类型会被识别为__SwiftValue,这是Firebase不兼容的类型。

简便解决方案:利用Codable转成Firebase兼容的字典

既然你的结构体已遵循Codable协议,只需将结构体对象转成[String: Any](数组则转成[[String: Any]]),即可直接传给Firebase。

步骤1:确保结构体遵循Codable

确认你的两个结构体已添加Codable协议(未添加则补充):

struct PrintifyLineItems: Codable {
    // 你的结构体属性,比如id、name、quantity等
}

struct PrintifyAddress: Codable {
    // 地址属性,比如street、city、zipCode等
}

步骤2:添加Codable转字典的扩展

写一个通用扩展,快速将任意Codable对象/数组转成Firebase支持的格式:

extension Encodable {
    /// 将单个Codable对象转成[String: Any]字典
    func toFirebaseDictionary() throws -> [String: Any] {
        let jsonData = try JSONEncoder().encode(self)
        guard let dict = try JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) as? [String: Any] else {
            throw NSError(domain: "StructConversion", code: 0, userInfo: [NSLocalizedDescriptionKey: "无法将结构体转成字典"])
        }
        return dict
    }
    
    /// 将Codable数组转成[[String: Any]]数组
    static func arrayToFirebaseDictionaries<T: Encodable>(_ array: [T]) throws -> [[String: Any]] {
        return try array.map { try $0.toFirebaseDictionary() }
    }
}

步骤3:修改上传函数

上传前先将结构体转成字典,再组装到values中:

func uploadMerchOrder(orderNo: String, email: String?, totalAmount: Int, usingCard: Bool, lineItems: [PrintifyLineItems], address: PrintifyAddress) {
    guard let user = AuthService.shared.user else { return }
    
    do {
        // 转换结构体为Firebase兼容的字典/数组
        let itemsDictArray = try PrintifyLineItems.arrayToFirebaseDictionaries(lineItems)
        let addressDict = try address.toFirebaseDictionary()
        
        let values: [String: Any] = [
            "userID": user.id,
            "email": email ?? user.email,
            "orderID": orderNo,
            "totalAmount": totalAmount,
            "usingCard": usingCard,
            "items": itemsDictArray,
            "address": addressDict
        ]
        
        merchOrders.child(orderNo).updateChildValues(values)
    } catch {
        print("结构体转换失败:\(error.localizedDescription)")
    }
}

原理说明

通过JSONEncoder将Codable结构体序列化为JSON数据,再用JSONSerialization将JSON数据转成字典——该字典内的所有类型均为Firebase支持的(字符串、数字、数组、嵌套字典),因此可以正常完成上传,不会再触发类型错误。

内容的提问来源于stack exchange,提问作者tHatpart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 23:45:34