2017-12-19 1 views
2

Ich arbeite gegen den Rest-API-Dienst, bei dem die Antworten in die Basisantwort unterteilt sind und alle anderen Antworten davon erben.Die Verwendung von Decodable mit Vererbung löst eine Ausnahme aus

Ich versuche, die gleiche Struktur für meine Antwortmodellklassen zu erstellen, mit der Decoder-Schnittstelle.

Allerdings habe ich Probleme mit der Decodierung einer geerbten Klasse.

Ich habe versucht, dieses Problem zu folgen: Using Decodable in Swift 4 with Inheritance

Aber ohne Glück.

Dies ist die erste Struktur:

class LoginResponse: BaseResponse{ 

    var Message: String? 

    private enum CodingKeys: String, CodingKey{ 
     case Message 
    } 

    required init(from decoder: Decoder) throws { 
     let container = try decoder.container(keyedBy: CodingKeys.self) 
     Message = try container.decode(String.self, forKey: .Message) 
     let superDecoder = try container.superDecoder() 
     try super.init(from: superDecoder) 
    } 
} 

class BaseResponse: Decodable { 

    var Status: Int? 

    private enum CodingKeys: String, CodingKey{ 
     case Status 
    } 

    required init(from decoder: Decoder) throws { 
     let container = try decoder.container(keyedBy: CodingKeys.self) // This line throws the exception 
     Status = try container.decode(Int.self, forKey: .Status) 
    } 
} 

Hier ist, wie ich versuche zu entschlüsseln:

let decoder = JSONDecoder() 
let json = "{\"Message\":\"saa\",\"Status\":200}" 
let login = try! decoder.decode(LoginResponse.self, from: json.data(using: .utf8)!) 

Wie ich oben geschrieben habe, diese Linie wirft die Ausnahme (in BaseResponse Klasse)

let container = try decoder.container(keyedBy: CodingKeys.self) 


Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.valueNotFound(Swift.KeyedDecodingContainer<SampleProject.BaseResponse.(CodingKeys in _084835F8074C7E8C5E442FE2163A7A00)>, Swift.DecodingError.Context(codingPath: [Foundation.(_JSONKey in _12768CA107A31EF2DCE034FD75B541C9)(stringValue: "super", intValue: nil)], debugDescription: "Cannot get keyed decoding container -- found null value instead.", underlyingError: nil)) 

Nicht sicher, wie man damit umgeht.

Vielen Dank im Voraus!

Antwort

2

Es gibt keine Notwendigkeit, die superDecoder zu verwenden ist, können Sie einfach das tun (ich änderte die Variablennamen in Kleinbuchstaben zu der Namenskonvention entsprechen)

class LoginResponse: BaseResponse { 

    let message: String 

    private enum CodingKeys: String, CodingKey{ 
     case message = "Message" 
    } 

    required init(from decoder: Decoder) throws { 
     let container = try decoder.container(keyedBy: CodingKeys.self) 
     message = try container.decode(String.self, forKey: .message) 
     try super.init(from: decoder) 
    } 
} 

class BaseResponse: Decodable { 

    let status: Int 

    private enum CodingKeys: String, CodingKey{ 
     case status = "Status" 
    } 

    required init(from decoder: Decoder) throws { 
     let container = try decoder.container(keyedBy: CodingKeys.self) 
     status = try container.decode(Int.self, forKey: .status) 
    } 
} 
  • decoder.decode(BaseResponse.self ... nur status
  • decoder.decode(LoginResponse.self ... decodiert decodiert status und message

Und nie en-/dec Ode mit try!. Behandeln Sie den Fehler.

+0

Danke! es funktioniert!. Können Sie bitte erläutern? Wie unterscheidet es sich von dem ähnlichen Link, den ich gepostet habe – dor506

+0

Ich bezweifle, dass die angegebene JSON-Struktur in der WWDC-Video ist das gleiche wie in Ihrer Frage. Trotzdem kann ich bestätigen, dass 'superDecoder' einen Fehler verursacht. – vadian

+0

Ich mache das, aber es verursacht eine Ausnahme, wenn ich versuche, den Wert der Kindklasse (als LoginResponse) zu bekommen, aber kein Problem in Super (wie BaseResponse) ich suche viel, aber debug zeigte keine Ausnahmebeschreibung –

Verwandte Themen