Using Decodable with inheritance raises an exception

你离开我真会死。 提交于 2019-12-07 05:51:13

问题


I'm working against Rest API service, where the responses are divided into Base response, and all other responses inherit from it.

I'm trying to building the same structure for my response model classes, using the Decoder interface.

However i'm having issues with the decoding of an inherited class.

I tried to follow this issue: Using Decodable in Swift 4 with Inheritance

But with no luck.

This is the initial structure:

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)
    }
}

Here's how I'm trying to decode:

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

As I wrote above, this line throws the exception (in BaseResponse class)

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))

Not sure how to deal with it.

Thanks in Advance!


回答1:


There is no need to use the superDecoder, you can simply do this (I changed the variable names to lowercase to conform to the naming convention)

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 ... decodes only status
  • decoder.decode(LoginResponse.self ... decodes status and message

And never en-/decode with try!. Handle the error.



来源:https://stackoverflow.com/questions/47886046/using-decodable-with-inheritance-raises-an-exception

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!