【问题标题】:Using Decodable with inheritance raises an exception将 Decodable 与继承一起使用会引发异常
【发布时间】:2018-06-01 20:00:42
【问题描述】:

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

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

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

我试图关注这个问题: 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))

不知道如何处理。

提前致谢!

【问题讨论】:

    标签: swift decodable


    【解决方案1】:

    没有必要使用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! 进行编码/解码。 处理错误

    【讨论】:

    • 谢谢!这是工作!。你能详细说明一下吗?它与我发布的类似链接有何不同
    • 我怀疑 WWDC 视频中给定的 JSON 结构与您的问题中的相同。不过我可以确认superDecoder 确实会引发错误。
    • 我这样做了,但是当我尝试获取子类的值(作为 LoginResponse)但在超级(作为 BaseResponse)中没有问题时它会导致异常我搜索了很多但调试没有显示异常描述
    • @vadian 谢谢!我需要几个小时才能最终找到您的解决方案,我很感激。
    猜你喜欢
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    相关资源
    最近更新 更多