我使用Codable
作为WebRequest响应,它返回一些预定义的字符串或数字。因此,我使用Enums作为这些响应。但是当一些意外的值到达Response时,我的Codable无法解码。
下面是一些代码,以便更好地理解.
class WebUser: Codable, Equatable {
static func == (lhs: WebUser, rhs: WebUser) -> Bool {
return lhs.id == rhs.id
}
...
var mobileNumberPrivacy: CommonPrivacyOption?
var emailPrivacy: CommonPrivacyOption?
var dobPrivacy: CommonPrivacyOption?
...
}
enum CommonPrivacyOption: Int, CaseIterable, Codable {
case privacyOnlyMe = 1, privacyPublic, privacyFriends, privacyFriendsOfFriends
//Does not help this optional init function
/*init?(rawValue: Int) {
switch rawValue {
case 1: self = .privacyOnlyMe
case 2: self = .privacyPublic
case 3: self = .privacyFriends
case 4: self = .privacyFriendsOfFriends
default: return nil
}
}*/
}
但是有时候我会从WebServer得到,0表示dobPrivacy
,此时我会得到DecodingError.dataCorrupted
异常,上下文为Cannot initialize CommonPrivacyOption from invalid Int value 0
当我得到其他值时,我期望dobPrivacy为零,然后是1/2/3/4。
- 编辑:**
let dict1 = [
"id": 2,
"mobileNumberPrivacy": 3,
"emailPrivacy": 4,
"dobPrivacy": 0 // Works perfectly with 1
]
do {
let data1 = try JSONSerialization.data(withJSONObject: dict1, options: .prettyPrinted)
let user1 = try JSONDecoder().decode(WebUser.self, from: data1)
print("User1 created")
}
catch DecodingError.dataCorrupted(let context) {
print(context.codingPath)
print(context.debugDescription)
}
catch {
print(error.localizedDescription)
}
我使用这个相同的可编码WebUser对象的个人资料细节,搜索用户和更多。所以可能是一些时候一个以上的关键字不会出现在WebRequest的响应。
5条答案
按热度按时间of1yzvn41#
我建议编写一个属性 Package 器来为您处理这个问题。
具体来说,让我们编写一个名为
NilOnDecodingError
的属性 Package 器,它将任何DecodingError
转换为nil
。下面是
NilOnDecodingError
的声明:我们定义它来 Package 任何类型,存储一个
Optional
。现在,当
Wrapped
类型为Decodable
时,我们可以使其符合Decodable
:当
Wrapped
类型是Encodable
时,我们可能也希望它是Encodable
:现在我们可以 Package
WebUser
的相应字段:为了进行测试,我们需要打印解码用户的字段:
现在我们可以尝试一下:
输出:
zengzsys2#
您需要在
WebUser
中创建一个自定义的Decodable
初始化器:或者,您可以在
CommonPrivacyOption
中实现Decodable
初始化器,并添加一个额外的case unknown
,如下所示:5t7ly7z53#
在我看来,编译器为枚举类型选择了错误的init,而不是
init(rawValue)
,它使用init(from:)
进行解码(这在某种程度上是有意义的)下面是一个解决方案,我们使用
WebUser
中的自定义init(from)
来覆盖此行为,该自定义init(from)
对原始值进行解码,然后创建一个枚举项下面是一个小示例
移动的:可选(1),电子邮件:无,出生日期:无
当然,如果您可以改变主意,将0转换为nil,那么我建议您扩展枚举以支持0值
那么它应该是开箱即用的,您不需要编写任何自定义代码。
vcudknz34#
我喜欢@alobaili的回答,因为它简单,提供了一个很好的解决方案。我想改进的一件事是使它更通用,以便任何
Decodable
(和Codable
)都可以用更少的代码来完成它。用法:
nvbavucw5#
谢谢Rob Mayoff的精彩回答。我只想补充一点-如果属性丢失,即使属性是可选的,解码也会失败。为了防止这种失败,请添加以下扩展: