Jonas Friederichs
Jonas Friederichs

Reputation: 11

Firebase Firestore: Encoder from custom structs not working

So I created a function in which I try to create a document in my Firestore in which user data is stored. But when upgrading my project to the Xcode 13.0 beta, the Firebase encoder has stopped working. Anyone else experiencing a similar problem?

My model looks like this:

struct User: Identifiable, Codable {
    
    @DocumentID var id: String?
    
    var auth_id: String?
    var username: String
    var email: String

    enum CodingKeys: String, CodingKey {
        case auth_id
        case username
        case email
    }
    
}

And the call to Firebase like this:

let newUser = User(auth_id: idToken, username: name, email: email)
            
try await databasemodel.database.collection("users").document(idToken).setData(newUser)

The Document is created with this code doesn't exist yet, but that worked earlier. Now when I compile I get the error: "Cannot convert value of type 'User' to expected argument type '[String : Any]'" No other errors are displayed, and I'm pretty sure the rest of the code works as expected.

Upvotes: 0

Views: 1758

Answers (2)

Vaidas Skardzius
Vaidas Skardzius

Reputation: 21

Just use Firestore.Encoder

extension Encodable {
    var dictionary: [String: Any]? {
       return try? Firestore.Encoder().encode(self)
    }
}

Upvotes: 2

Byron Coetsee
Byron Coetsee

Reputation: 3593

So I ran into a similar issue with Codables... I've made this little extension that's saved me. Maybe it works for you too :)

extension Encodable {
    /// Convenience function for object which adheres to Codable to compile the JSON
    func compile () -> [String:Any] {
        guard let data = try? JSONEncoder().encode(self) else {
            print("Couldn't encode the given object")
            preconditionFailure("Couldn't encode the given object")
        }
        return (try? JSONSerialization
            .jsonObject(with: data, options: .allowFragments))
            .flatMap { $0 as? [String: Any] }!
    }
}

You can then do

try await databasemodel.database.collection("users").document(idToken).setData(newUser.compile())

Note. I didn't test this. I'm simply providing the extension which solved my problem when faced with the same thing.

Upvotes: 1

Related Questions