将Decodable与继承一起使用会引发异常

时间:2017-12-19 11:30:41

标签: swift decodable

我正在使用Rest API服务,其中响应被分为Base响应,所有其他响应都从它继承。

我正在尝试使用Decoder接口为我的响应模型类构建相同的结构。

但是我在解码继承类时遇到了问题。

我试图关注此问题: Using Decodable in Swift 4 with Inheritance

但没有运气。

这是初始结构:

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

以下是我尝试解码的方法:

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

正如我上面所写,这一行抛出异常(在BaseResponse类中)

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

不确定如何处理它。

提前致谢!

1 个答案:

答案 0 :(得分:6)

不需要使用superDecoder,您可以简单地执行此操作(我将变量名称更改为小写以符合命名约定)

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 ...仅解码status
  • decoder.decode(LoginResponse.self ...解码statusmessage

永远不会使用try!进行解码。 处理错误