2017-09-09 4 views
1

Ich habe eine Swift-App, die ich gerade konvertiere, um das Codable-Protokoll zu verwenden (anstelle von EVReflection, das so viel geändert hat, dass ich konnte) mach es nicht mehr funktionieren). Bei der Transaktion mit dem App-Server generiert mein Code ein Objekt der Klasse "ServerResponse", das eine Anzahl von Variablen enthält - eine davon ist "responseObject" - das können beliebig viele verschiedene Objekte von einem Benutzer zu einer Nachricht sein Andere. Da Codable standardmäßig nicht "decodeIfPresent" verwendet, bekam ich während bestimmter Transaktionen Fehler und musste init (vom Decoder: Decoder) überschreiben, um dies zu verhindern. Jetzt habe ich die Herausforderung herauszufinden, wie ich entweder die rohe JSON-Zeichenfolge für die Decodierung in den korrekten Objekttyp später durch die aufrufende Methode oder eine andere ähnliche Korrektur intakt lassen kann. Bottom line: Ich brauche responseObject, um flexibel zu sein und jeden Objekttyp zuzulassen, den mein Server auswählt.Swift 4 - Codierbar - Wie man verschiedene Objekttypen für einen Schlüssel beim Dekodieren zulässt

Wenn jemand irgendwelche Vorschläge hat, wäre ich dankbar. Ich werde glücklich sein, Code zu teilen, wenn das helfen wird, aber ich habe nicht gedacht, dass es sein würde, da diese Frage größtenteils konzeptionell ist.

+0

Die allgemeine Lösung für den Versuch, etwas zu dekodieren, das einen von mehreren Typen haben kann, ist der Versuch, es als einen Typ zu dekodieren, und wenn dies aufgrund einer Typabweichung fehlschlägt, versuchen Sie den nächsten Typ. Ist 'responseObject' so oder ist es ein völlig unbeschränkter Typ? Können Sie ein konkretes Beispiel dafür geben, wie die JSON-Payload aussehen könnte? –

+0

Es ist nicht vollständig untrainiert, aber es gibt 34 verschiedene Arten von Objekten an dieser Stelle in meiner App, die bestanden werden könnten. Was ich wirklich gerne hätte, wäre, das rohe JSON vollständig unberührt zu lassen, so dass ich es manuell von der aufrufenden Methode entschlüsseln könnte. Gibt es eine Möglichkeit, das zu tun? – Joel

+1

Nicht im Moment, nein. Es wird derzeit ein Merkmal betrachtet. –

Antwort

2

Sie können etwas ähnliches tun: -

struct CustomAttribute: Codable { 
var attributeCode: String? 
var intValue: Int? 
var stringValue: String? 
var stringArrayValue: [String]? 

enum CodingKeys: String, CodingKey { 

    case attributeCode = "attribute_code" 
    case intValue = "value" 
    case stringValue 
    case stringArrayValue 
} 

init(from decoder: Decoder) throws { 
    let values = try decoder.container(keyedBy: CodingKeys.self) 

    attributeCode = try values.decode(String.self, forKey: .attributeCode) 
    if let string = try? values.decode(String.self, forKey: .intValue) { 
     stringValue = string 
    } else if let int = try? values.decode(Int.self, forKey: .intValue) { 
     intValue = int 
    } else if let intArray = try? values.decode([String].self, forKey: .intValue) { 
     stringArrayValue = intArray 
    } 
} 

} 

Hier Wert kann von drei Typen sein, und ich identifiziere manuell, welche Art es ist.

Verwandte Themen