为啥使用 JSONDecoder.decode 方法时没有调用 Decodable 的 init 方法?

Posted

技术标签:

【中文标题】为啥使用 JSONDecoder.decode 方法时没有调用 Decodable 的 init 方法?【英文标题】:Why Decodable's init method isn't called when using JSONDecoder.decode method?为什么使用 JSONDecoder.decode 方法时没有调用 Decodable 的 init 方法? 【发布时间】:2019-06-11 17:14:16 【问题描述】:

我正在尝试覆盖 JSONDecoder 解码数据的方式。

我尝试了以下方法:

struct Response : Decodable 
    init(from decoder: Decoder) throws 
        print("Hello")
    


let result = try JSONDecoder().decode(Response.self, from: Data())

但是init(from:) 没有被调用。 基本上我希望JSONDecoder 在将空数据解码为空Response 对象时始终成功

【问题讨论】:

它没有被调用,因为你没有给它任何 JSON 数据来解码。 【参考方案1】:

空的Data 对象导致init 方法抛出错误

给定的数据不是有效的 JSON。

在“Hello”被打印之前。


如果你想得到一个空的Response 对象(假设你不必调用任何指定的初始化器)捕获dataCorrupted 解码错误

struct Response : Decodable 

var response : Response?
do 
    response = try JSONDecoder().decode(Response.self, from: Data())
 catch DecodingError.dataCorrupted(let context) where (context.underlyingError as NSError?)?.code == 3840  // "The given data was not valid JSON."
    response = Response()
 catch  print(error) 

【讨论】:

【参考方案2】:

谁来到这个页面寻找一种解决方案来强制在您只需要使用的可解码类上使用 INIT:

required init(from decoder: Decoder) throws 

完整示例:

class DeviceListElement: Codable 
    
    var firmwareVersion, deviceName: String
    var status: Int
    
    
    enum CodingKeys: String, CodingKey 
        case firmwareVersion = "fwVer"
        case deviceName
        case status
    
    

    required init(from decoder: Decoder) throws 
        
        let container = try decoder.container(keyedBy: CodingKeys.self)
        firmwareVersion = try container.decode(String.self, forKey: .firmwareVersion)
        deviceName = try container.decode(String.self, forKey: .deviceName)
        status = try container.decode(Int.self, forKey: .status)
        
        
        //if is optional use this: container.decodeIfPresent(String.self, forKey: .blabla)
    
    

【讨论】:

以上是关于为啥使用 JSONDecoder.decode 方法时没有调用 Decodable 的 init 方法?的主要内容,如果未能解决你的问题,请参考以下文章

Swift 5:如何从 JSONDecoder().decode 获取数据?

swift中的T.Type是啥

Alamofire 得到回应

在 Eclipse 中使用 aar - 为啥第 3 方活动在构建时解决而不是运行时解决?

如果启用了环回,为啥发送方收不到它的多播 UDP 数据包?

使用泛型/可编码 w/ API 响应 204 NO CONTENT