- 在你回答之前 *
我知道
- 空字符串是无效的
URL
- 我可以为
Employee
写一个自定义的解码器 - 我可以将
url
声明为String
我正在寻找一个更好的解决方案来解码可选的URL
本身。我希望有一些Codable
魔法我错过了!
所以,我有JSON,例如
let json = Data("""
{
"name": "Fred",
"url": ""
}
""".utf8)
以及包含可选URL的相应对象...
struct Employee: Decodable {
let name: String
let url: URL?
}
由于JSON中的url
无效,我希望它解码为nil
,而不是抛出错误。
尝试以下操作不起作用(它不会被调用)...
extension Optional where Wrapped == URL {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
self = try container.decode(URL.self)
} catch {
self = nil
}
}
}
在过去,我用…
struct FailableDecodable<T: Decodable>: Deodable {
let wrapped: T?
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
self.wrapped = try container.decode(T.self)
} catch {
print("Error decoding failable object: \(error)")
self.wrapped = nil
}
}
}
struct Employee: Decodable {
let name: String
let url: FailableDecodable<URL>?
}
但这需要我不断地引用url.wrapped
。
有更好的解决方案吗?
3条答案
按热度按时间9fkzdhlc1#
如果你使用的是Swift 5.1,你可以使用
@propertyWrapper
:编辑-可编码版本
如果你需要顶级结构体也是
Encodable
,你可以使用Codable
一致性来封装属性。如果
url
是nil
,则将输出一个带有url: null
的JSON如果您不希望在
nil
时输出url
属性,则需要在Employee
中实现自定义编码(使用encode(to:)
)(这将减少使用属性 Package 器的好处)。**注意:**使用
encode(to:)
的默认实现(不实现)也可以,但当url
为nil
时输出空对象:1wnzp6jl2#
如果你得到
Return from initializer without initializing all stored properties
警告,你的Codable
结构初始化器包含下面的@FailableDecodable
将解决它。xqkwcwgp3#
除了上面优秀的
@propertyWrapper
解决方案之外,我还想修复JSON中不存在url
键时的故障。它永远不会到达
init(from decoder: Decoder)
方法,因为键不存在,所以我们需要在KeyedCodingContainer
上添加一个扩展来处理这种情况。我还需要手动向
FailableDecodable
添加另一个初始化器以使其能够编译。我发现有了这些变化,上面@rraphael的答案是完美的!