Swift 可编码初始化
Swift Codable init
我想在 Swift Coding/Encoding 功能完成对 JSON 的解码后做一些初始化逻辑。
struct MyStruct: Codable {
let id: Int
var name: String
init() {
name = "\(id) \(name)"
}
}
但是我得到编译器错误:
Return from initializer without initializing all stored properties
我很清楚,因为 init() 要我初始化所有属性。但是添加一个具有所有需要的属性的 init() 也不能解决它,因为当 Codable 启动时这个初始化器没有被调用(!):
init(id: Int, name: String) {
// This initializer is not called if Decoded from JSON!
self.id = id
self.name = "\(id) \(name)"
}
尽管如此 - 有没有办法在解码完成后执行一些初始化逻辑,但无需为每个 属性 手动执行所有解码?所以不用每次都实施init(from decoder: Decoder)
。在这个简短的示例中,我只有两个简单的属性,但生产代码由数千个属性组成。
谢谢。
要么免费获得一切但标准化,要么必须编写自定义初始化程序,如
struct MyStruct: Codable {
let id: Int
var name: String
private enum CodingKeys : String, CodingKey { case id, name }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
let decodedName = try container.decode(String.self, forKey: .name)
name = "\(id) \(decodedName)"
}
}
您可以实现 init()
,但这与解码功能无关,您必须为所有非可选属性分配一个默认值,这就是错误所说的。
使用工厂方法,首先使用 init(from:)
,然后调用您的自定义初始化代码
struct Foo: Decodable {
let name: String
let id: Int
var x: String!
private mutating func finalizeInit() {
self.x = "\(name) \(id)"
}
static func createFromJSON(_ data: Data) -> Foo? {
guard var f = try? JSONDecoder().decode(Foo.self, from: data) else {
return nil
}
f.finalizeInit()
return f
}
}
let sampleData = """
{ "name": "foo", "id": 42 }
""".data(using: .utf8)!
let f = Foo.createFromJSON(sampleData)
我想在 Swift Coding/Encoding 功能完成对 JSON 的解码后做一些初始化逻辑。
struct MyStruct: Codable {
let id: Int
var name: String
init() {
name = "\(id) \(name)"
}
}
但是我得到编译器错误:
Return from initializer without initializing all stored properties
我很清楚,因为 init() 要我初始化所有属性。但是添加一个具有所有需要的属性的 init() 也不能解决它,因为当 Codable 启动时这个初始化器没有被调用(!):
init(id: Int, name: String) {
// This initializer is not called if Decoded from JSON!
self.id = id
self.name = "\(id) \(name)"
}
尽管如此 - 有没有办法在解码完成后执行一些初始化逻辑,但无需为每个 属性 手动执行所有解码?所以不用每次都实施init(from decoder: Decoder)
。在这个简短的示例中,我只有两个简单的属性,但生产代码由数千个属性组成。
谢谢。
要么免费获得一切但标准化,要么必须编写自定义初始化程序,如
struct MyStruct: Codable {
let id: Int
var name: String
private enum CodingKeys : String, CodingKey { case id, name }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
let decodedName = try container.decode(String.self, forKey: .name)
name = "\(id) \(decodedName)"
}
}
您可以实现 init()
,但这与解码功能无关,您必须为所有非可选属性分配一个默认值,这就是错误所说的。
使用工厂方法,首先使用 init(from:)
,然后调用您的自定义初始化代码
struct Foo: Decodable {
let name: String
let id: Int
var x: String!
private mutating func finalizeInit() {
self.x = "\(name) \(id)"
}
static func createFromJSON(_ data: Data) -> Foo? {
guard var f = try? JSONDecoder().decode(Foo.self, from: data) else {
return nil
}
f.finalizeInit()
return f
}
}
let sampleData = """
{ "name": "foo", "id": 42 }
""".data(using: .utf8)!
let f = Foo.createFromJSON(sampleData)