Swift 可解码,不';t解码具有无效值的可选枚举
我定义了如下枚举:Swift 可解码,不';t解码具有无效值的可选枚举,swift,swift4,codable,Swift,Swift4,Codable,我定义了如下枚举: enum ClubLevel: Int, Codable { case golden = 1, silver, bronze } 在我的结构中,我有一个类型为ClubLevel的可选属性,当我在init(来自解码器:解码器)中解码该属性时: 我面对这个错误: debugDescription:“无法从无效的Int值0初始化ClubLevel”,underlineError:nil“ 我想知道即使这个属性是可选的,解码器也不会继续 有什么想法吗?线路 self.clu
enum ClubLevel: Int, Codable {
case golden = 1, silver, bronze
}
在我的结构中,我有一个类型为ClubLevel
的可选属性,当我在init(来自解码器:解码器)
中解码该属性时:
我面对这个错误:
debugDescription:“无法从无效的Int值0初始化ClubLevel”,underlineError:nil“
我想知道即使这个属性是可选的,解码器也不会继续
有什么想法吗?线路
self.clubLevel = try container.decode(ClubLevel?.self, forKey: .clubLevel)
不尝试解码ClubLevel
,如果不成功,则分配nil
。它所做的是:
clubLevel
键的nil
(在JSON中表示为null
)。如果不成功ClubLevel
键的ClubLevel
。如果不成功clubLevel
键的值既不是nil
也不是有效的clubLevel
表示,则会抛出一个错误。您会注意到,这也意味着如果clubLevel
键完全丢失(而不是出现值nil
),则会抛出一个错误
忽略缺少的键是通过decodeIfPresent
完成的:
self.clubLevel = try container.decodeIfPresent(ClubLevel.self, forKey: .clubLevel)
现在将:
clubLevel
键,则返回nil
。如果它们的键存在clubLevel
键的nil
(在JSON中表示为null
)。如果不成功ClubLevel
键的ClubLevel
。如果不成功init(from:)
实现中解码选项的默认行为。在您的情况下,它仍然会引发错误,因为clubLevel
键的值不是有效的clubLevel
如果您只想尝试解码ClubLevel
,在解码过程中分配nil
,但由于任何原因(密钥丢失、无效值等),则需要使用try?
:
self.clubLevel = try? container.decode(ClubLevel.self, forKey: .clubLevel)
我遇到了同样的问题,我想我应该为任何感兴趣的人添加我的解决方案 其思想是将枚举包装在以下结构中:
struct OptionalDecodableEnum<T>: Decodable where T: RawRepresentable, T.RawValue: Decodable {
let value: T?
init(from decoder: Decoder) throws {
value = T(rawValue: try decoder.singleValueContainer().decode(T.RawValue.self))
}
}
我正在寻找一种方法来解决本文中描述的类似问题-仅针对枚举值数组而不是单个枚举值。由于这是在寻找此问题的答案时出现的第一篇文章,我想在这里分享我的解决方案,以防它可能会帮助有类似问题的人:) 有问题的例子:
{
"exampleArray": [
"FirstExample",
"SecondExample",
"abcde123",
"FourthExample"
]
}
/。。。
//用法
init(来自解码器:解码器)抛出{
let container=try decoder.container(keyedBy:CodingKeys.self)
enumArray=try?container.decodeEnumArray([EnumType].self,forKey:.enumArray)
}
// ...
扩展键DecodingContainer{
func decodeEnumArray([T]。类型,forKey:Self.key)抛出->[T],其中T.RawValue:Decodable{
返回try decode([T.RawValue].self,forKey:key).map{T(RawValue:$0)}.compactMap{$0}
}
}
enumArray将成为
[第一个示例,第二个示例,四个示例]
谢谢你的评论@hamish你能解释一下try?container.decode(ClubLevel.self,forKey:.ClubLevel)
和try container.decode(ClubLevel?.self,forKey:.ClubLevel)之间的区别吗
。您可以将您的评论作为答案发布。如果我们需要在任何失败原因上指定默认值,该怎么办?@Jan您可能希望使用nil聚合运算符,例如(try?container.decode(ClubLevel.self,forKey:.ClubLevel))??默认值啊,我缺少括号了。谢谢!
struct Foo: Decodable {
enum ClubLevel: Int, Codable {
case golden = 1, silver, bronze
}
let clubLevel: OptionalDecodableEnum<ClubLevel>
}
let foo = try jsonDecoder.decode(Foo.self, from: data)
print(String(describing: foo.clubLevel.value))
{
"exampleArray": [
"FirstExample",
"SecondExample",
"abcde123",
"FourthExample"
]
}