2 votes

Sous-classement du type décodable générique rapide

EDIT : Comme Rob Napier a écrit , le problème existe dans Xcode 9.2. Dans Xcode 9.3 le problème n'est plus pertinent.

Les réponses json de mon serveur sont toutes emballées dans data objet :

{ 
    "data": {...}
}

J'ai donc le type générique suivant pour analyser le JSON :

class DataContainer<T: Decodable>: Decodable {

    let data: T

    init(data: T)
        self.data = data
    }
}

La plupart du temps, cela fonctionne bien, mais il y a une réponse pour laquelle je dois également analyser les données suivantes included J'ai donc créé un champ SpecificDataContainer sous-classe :

class SpecificDataContainer: DataContainer<DataObject> {
    let included: [IncludedObject]

    init() {
        included = []
        super.init(data: DataObject(id: ""))
    }
}

L'implémentation ci-dessus me donne une erreur de compilation 'required' initializer 'init(from:)' must be provided by subclass of 'DataContainer' .

J'ai mis en place init(from:) en el SpecificDataContainer mais le compilateur me donne toujours la même erreur.

Il semble que je manque quelque chose d'évident ici. Qu'est-ce que je fais de mal ? Voici mon code complet :

import Foundation

let jsonData = """
{
    "data": {
        "id": "some_id"
    },
    "included": [
        {
            "id": "some_id2"
        }
    ]
}
""".data(using:.utf8)!

struct DataObject: Decodable {
    let id: String
}

struct IncludedObject: Decodable {
    let id: String
}

class DataContainer<T: Decodable>: Decodable {
    let data: T

    init(data: T) {
        self.data = data
    }
}

class SpecificDataContainer: DataContainer<DataObject> {
    let included: [IncludedObject]

    init() {
        included = []
        super.init(data: DataObject(id: ""))
    }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        var includedArray = try container.nestedUnkeyedContainer(forKey: .included)

        var includedObjects:[IncludedObject] = []
        while !includedArray.isAtEnd {
            let includedObject = try includedArray.decode(IncludedObject.self)
            includedObjects.append(includedObject)
        }
        self.included = includedObjects

        try super.init(from: decoder)
    }

    private enum CodingKeys: String, CodingKey {
        case data = "data"
        case included = "included"
    }
}

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
if let obj = try? decoder.decode(SpecificDataContainer.self, from: jsonData) {
    print("object id \(obj.data.id)")
} else {
    print("Fail!")
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X