Swift 4添加了新Codable协议。当我使用JSONDecoder它时,似乎要求类的所有非可选属性Codable在JSON中具有键,否则会引发错误。
Codable
JSONDecoder
使类的每个属性都是可选的似乎是不必要的麻烦,因为我真正想要的是使用json中的值或默认值。(我不希望该属性为零。)
有没有办法做到这一点?
class MyCodable: Codable { var name: String = "Default Appleseed" } func load(input: String) { do { if let data = input.data(using: .utf8) { let result = try JSONDecoder().decode(MyCodable.self, from: data) print("name: \(result.name)") } } catch { print("error: \(error)") // `Error message: "Key not found when expecting non-optional type // String for coding key \"name\""` } } let goodInput = "{\"name\": \"Jonny Appleseed\" }" let badInput = "{}" load(input: goodInput) // works, `name` is Jonny Applessed load(input: badInput) // breaks, `name` required since property is non-optional
我更喜欢的方法是使用所谓的DTO-数据传输对象。它是一个结构,符合Codable并表示所需的对象。
struct MyClassDTO: Codable { let items: [String]? let otherVar: Int? }
然后,您只需使用该DTO初始化要在应用程序中使用的对象。
class MyClass { let items: [String] var otherVar = 3 init(_ dto: MyClassDTO) { items = dto.items ?? [String]() otherVar = dto.otherVar ?? 3 } var dto: MyClassDTO { return MyClassDTO(items: items, otherVar: otherVar) } }
这种方法也是不错的选择,因为您可以按自己的意愿重命名和更改最终对象。很明显,比手动解码需要更少的代码。此外,通过这种方法,您可以将网络层与其他应用程序分开。