KeyedDecodingContainer 如何实现 decode<T>(_ type: T.Type, forKey key: KeyedDecodingContainer<K&



我正在试验Decodable,无法弄清楚编译器如何为特定的Decodable实例(如Book)合成decode(_ type: Decodable.Protocol, forKey key: CodingKey)函数。

struct Book: Codable {
var title: String
var pages: Int
var author: String
var coauthor: String
}
struct Bookstore: Codable {
var book: Book
var owner: String
}

我试着自己写一个decode(_:forKey:)函数,这样我就可以更好地了解编译器是如何合成它的,但我完全空白。我开始为Book.Type重载decode(_:forKey:)函数,但这就是我所得到的。

extension KeyedDecodingContainer {
func decode(_ type: Book.Type, forKey key: CodingKey) throws -> Book {
print("I am about to decode a Book from the data keyed by (key.stringValue)")
// I have no clue what to put here
}
}

如果有人能帮我完成这个实现,我将非常感激,因为它将帮助我更好地理解解码过程。

提前感谢!

<标题>

编辑:我已经试过了:

extension KeyedDecodingContainer {
func decode(_ type: Book.Type, forKey key: CodingKey) throws -> Book {
print("I am about to decode a Book from the data keyed by (key.stringValue)")
let decoder = try self.superDecoder(forKey: key as! K)
return try Book(from: decoder)
}
}

这是有效的,但我不知道as! K到底在做什么,也不知道superDecoder(forKey:)做什么。此外,我不确定在这种情况下使用强制铸造是否被认为是危险的。有更安全的方法吗?

我想你误解了一些东西,编译器不合成任何东西。decode泛型,其泛型参数T约束为Decodable。这意味着一旦声明了它,它将适用于所有符合Decodable的类型。没有为Book生成单独的实现。这都是相同的实现,只是不同的Ts。你应该关注的签名是:

func decode<T>(_ type: T.Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> T where T : Decodable

它是如何实现的?源代码说:

public func decode<T: Decodable>(
_ type: T.Type,
forKey key: Key
) throws -> T {
return try _box.decode(T.self, forKey: key)
}

所以像"如果你不得不这样做,你将如何实现[这个方法]?"不是很有意义,因为该方法已经被实现了,您不必自己实现它。

显然这个实现对于理解它是如何工作的不是很有用。它只是将调用委托给其他东西。调用最终被委托给KeyedDecodingContainerProtocol,而KeyedDecodingContainerProtocol的哪个实现取决于您正在使用的解码器。例如,JSONDecoder使用的解码容器与PropertyListDecoder不同。

现在的问题是,KeyedDecodingContainerProtocol中的decode方法是如何实现的?正如我们已经确定的,这取决于解码器。JSON解码器将做一些特定于JSON的事情,属性列表解码器将做一些特定于属性列表的事情,但最终它们可能会调用T.init(from:)来获得T的实例。KeyedDecodingContainerProtocol.decode是您可以自己实现的。如果您正在编写自己的解码器,则需要实现此功能。T.init(from:)也是你应该实现的东西,如果你想让你的可编码对象以自定义的方式解码。

我找不到JSONDecoder的源代码,所以这里有一个开源的XML解码器,你可以探索:https://github.com/ShawnMoore/XMLParsing

这就是他们如何实现KeyedDecodingContainerProtocol.decode的。这里调用unbox,这里调用T.init(from:)

相关内容

  • 没有找到相关文章

最新更新