amirbt17
amirbt17

Reputation: 611

Decoding Is Not Supported ("DocumentID values can only be decoded with Firestore.Decoder")

I have the following struct:

struct Recipe: Codable {
    @DocumentID var id: String?
    var vegetarian: Bool?
}

And this is how I'm parsing the data from Firestore:

do {
    let decoder = JSONDecoder()
    let recipeToDisplay = try decoder.decode(Recipe.self, from: data!)
                    
    let uuid = UUID().uuidString
                    
    FirestoreService.createRecipe(
        documentId: uuid,
        vegetarian: recipeToDisplay.vegetarian ?? false
    ) { recipeURL in
        print("success")
    }
} catch {
    print("Error parsing response data: \(error)")
}

The catch statement is getting called and I'm getting the following error message: decodingIsNotSupported("DocumentID values can only be decoded with Firestore.Decoder").

All the documentation I've researched has pointed me towards using JSONDecoder() to parse the data and I can't find anything on Firestore.Decoder. Is there a different way that I should be parsing the data?

Upvotes: 5

Views: 1174

Answers (3)

anomaddev
anomaddev

Reputation: 9

I had a similar issue causing this error. I was pulling a document by reference, checking if it exists and had data, then decoding that data to an object. Not sure if you are doing something similar but I will put it in terms of your application.

struct Recipe: Codable {
    @DocumentID var id: String?
    var vegetarian: Bool?
}

// Searching for document
do { 
    let dbRef = Firestore.firestore().collection("recipes")
    let docRef = dbRef.document("EKUU2A1d9w8D20xxbm0i")
    let docSnap = docRef.getDocument()

    guard docSnap.exists(), let data = docSnap.data()
    else { throw NSError() }

    // Not passing the document reference will throw the error you're receiving
    // let recipe try Firestore.Decoder().decode(Recipe.self, from: data)
    
    // So make sure to include the document reference in the decode function
    let recipe = try Firestore.Decoder().decode(Recipe.self, from: data, in: docRef)
}

Upvotes: 0

user139816
user139816

Reputation: 214

My problem was that I wasn't using an explicit Codable implementation. Unfortunately you have to add in all that nonsense boiler plate in order for it to work. Rather than use the default.

So go ahead and bloat your model with:

enum CodingKeys: String, CodingKey

init(from decoder: Decoder)

func encode(to encoder: Encoder)

Upvotes: 0

amirbt17
amirbt17

Reputation: 611

The issue was that I was trying to decode id from a source that didn't have an id property. Excluding id from my CodingKeys resolved the issue.

struct Recipe: Codable {
    @DocumentID var id: String?
    var vegetarian: Bool?
    
    private enum CodingKeys: String, CodingKey {
        case id
        case vegetarian
    }
}

Upvotes: 4

Related Questions