为啥使用 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 获取数据?