2017-10-18 10 views
4

il est conforme au protocole codable, je ne peux pas sauter facilement propriété facultative de classe non codableIgnorer les propriétés non codable en option dans l'objet codable

En Ride struct nous voulons ignorer encodage et décodage de driver propriété , et il suffit de laisser nil lors du décodage

struct Ride: Codable { 

    public var number: String 
    public var passenger: Passenger? // Codable conforming 
    public var driver: Driver?  // NSObject subclass, doesn't conform to Codable 

    enum CodingKeys: String, CodingKey { 
     case number 
     case passenger 
    } 
    } 

Dans ce cas, je reçois une erreur de compilation

Type « Driver » ne se conforme pas au protocole « décodables »

Jusqu'à présent, la seule solution que je suis venu avec, est de Coder et Decode manuellement en fournissant des méthodes suivantes:

public init(from decoder: Decoder) throws { 
    let values = try decoder.container(keyedBy: CodingKeys.self) 
    number = try? values.decode(String.self, forKey: .number) 
    passenger = try? values.decode(Passenger.self, forKey: .passenger) 
} 

public func encode(to encoder: Encoder) throws { 
    var container = encoder.container(keyedBy: CodingKeys.self) 
    try container.encode(number, forKey: .number) 
    try container.encode(passenger, forKey: .passenger) 
} 

est là une autre façon d'ignorer une propriété optionnelle? Ce serait beaucoup plus facile avec les plus gros modèles.

+0

Ceci est un bug, voir cette chaîne de commentaires: https://stackoverflow.com/questions/46104870/swift-4-decodable-additional-variables/46105080#comment79173417_46105080 – Hamish

Répondre

8

Essayez de fournir une valeur par défaut pour driver. Par exemple, cette compilation sans erreurs sur Xcode 9.0:

struct Ride: Codable { 
    public var number: String 
    public var passenger: Passenger? 
    public var driver: Driver? = nil 

    private enum CodingKeys: String, CodingKey { 
     case number 
     case passenger 
    } 
} 

struct Passenger: Codable { /* ... */ } 

class Driver: NSObject { /* ... */ } 

Test rapide:

let rideJSON = 
""" 
{ 
    "number": "123" 
} 
""".data(using: .utf8)! 

let ride = try! JSONDecoder().decode(Ride.self, from: rideJSON) 
print(ride) /* Ride(number: "123", passenger: nil, driver: nil) */ 

Soit dit en passant, j'ai utilisé un private CodingKeys parce que c'est ce que le compilateur fait par défaut comme bien;)

+1

L'erreur du compilateur imprimée est remarquablement utile sur cette question: 'note: ne peut pas synthétiser automatiquement 'Decodable' parce que 'driver' n'a pas de CodingKey correspondante et n'a pas de valeur par défaut'' – mklbtz

+0

@mklbtz Good catch! Probablement une amélioration par ** Xcode 9.2 ** ... * ou * nous avons complètement raté ce message (utile!) La première fois;) Beaucoup de gens ne prennent même pas la peine de lire/interpréter de tels messages ... –