如何从该对象中的另一个 init 方法解码可编码对象
How to decode a codable object from another init method in that object
我在 swift 中有一个 Codable
类型,它的 init 方法接受从我无法控制的代码调用的 json Data
。我可以使用此 Data
自动反序列化该对象吗?
class SomeType : Codable {
// From this init I want to call into the auto generated `Decodable` init method
// with a decoder that can decode the passed in `Data`
convenience init(data: Data) {
// This is the imaginary code I'm looking for below
let decoder = JSONDecoder(for: data)
self.init(from: decoder)
}
}
这样的事情可能吗? Codable 已经为我自动实现了 encode/decode,我想使用它 :)
请尝试使用 struct
。
struct SomeType: Codable {
init(data: Data) {
do {
self = try JSONDecoder().decode(SomeType.self, from: data)
} catch {
print(error)
}
}
}
现在您可以解析 data
,例如,
let response = SomeType(data: data)
print(response)
是的,你可以,但是你必须将错误移交给调用者,否则你会得到一个关于没有初始化存储属性的编译器错误。
struct SomeType: Codable {
let name : String
let id : Int
init(data: Data) throws {
self = try JSONDecoder().decode(SomeType.self, from: data)
}
}
let json = """
{"name":"Foo","id":12}
"""
let result = try! SomeType(data: Data(json.utf8))
print(result)
如果您可以使用结构,那么@vadian 的答案就有效。
如果您出于某种原因需要引用语义,您可以使用与调用方接口一致的适配器包装数据 class。
根据您希望如何处理错误(return 可选或抛出),您将实现不同的 init(data:) 方法。
如果您的调用者可以捕捉到错误,您可以这样做:
class AdapterType {
let someType: SomeType
init(data: Data) throws {
self.someType = try JSONDecoder().decode(SomeType.self, from: data)
// ... add do/catch/throw if you need to remap the error for your caller
}
}
let jsonData = """
{"name":"Foo",\"id":12}
""".data(using: .utf8)!
let result = try? AdapterType(data: jsonData)
print("\(result?.someType.name ?? "(unset)")")
如果您的调用者不关心调用失败的原因并且可以处理 returned 可选,您可以使用可失败的初始化程序,如下所示:
class AdapterType {
let someType: SomeType
init?(data: Data) {
guard let someType = try? JSONDecoder().decode(SomeType.self, from: data)
else { return nil }
self.someType = someType
}
}
let jsonData = """
{"name":"Foo",\"id":12}
""".data(using: .utf8)!
let result = try? AdapterType(data: jsonData)
print("\(result?.someType.name ?? "(unset)")")
我在 swift 中有一个 Codable
类型,它的 init 方法接受从我无法控制的代码调用的 json Data
。我可以使用此 Data
自动反序列化该对象吗?
class SomeType : Codable {
// From this init I want to call into the auto generated `Decodable` init method
// with a decoder that can decode the passed in `Data`
convenience init(data: Data) {
// This is the imaginary code I'm looking for below
let decoder = JSONDecoder(for: data)
self.init(from: decoder)
}
}
这样的事情可能吗? Codable 已经为我自动实现了 encode/decode,我想使用它 :)
请尝试使用 struct
。
struct SomeType: Codable {
init(data: Data) {
do {
self = try JSONDecoder().decode(SomeType.self, from: data)
} catch {
print(error)
}
}
}
现在您可以解析 data
,例如,
let response = SomeType(data: data)
print(response)
是的,你可以,但是你必须将错误移交给调用者,否则你会得到一个关于没有初始化存储属性的编译器错误。
struct SomeType: Codable {
let name : String
let id : Int
init(data: Data) throws {
self = try JSONDecoder().decode(SomeType.self, from: data)
}
}
let json = """
{"name":"Foo","id":12}
"""
let result = try! SomeType(data: Data(json.utf8))
print(result)
如果您可以使用结构,那么@vadian 的答案就有效。
如果您出于某种原因需要引用语义,您可以使用与调用方接口一致的适配器包装数据 class。
根据您希望如何处理错误(return 可选或抛出),您将实现不同的 init(data:) 方法。
如果您的调用者可以捕捉到错误,您可以这样做:
class AdapterType {
let someType: SomeType
init(data: Data) throws {
self.someType = try JSONDecoder().decode(SomeType.self, from: data)
// ... add do/catch/throw if you need to remap the error for your caller
}
}
let jsonData = """
{"name":"Foo",\"id":12}
""".data(using: .utf8)!
let result = try? AdapterType(data: jsonData)
print("\(result?.someType.name ?? "(unset)")")
如果您的调用者不关心调用失败的原因并且可以处理 returned 可选,您可以使用可失败的初始化程序,如下所示:
class AdapterType {
let someType: SomeType
init?(data: Data) {
guard let someType = try? JSONDecoder().decode(SomeType.self, from: data)
else { return nil }
self.someType = someType
}
}
let jsonData = """
{"name":"Foo",\"id":12}
""".data(using: .utf8)!
let result = try? AdapterType(data: jsonData)
print("\(result?.someType.name ?? "(unset)")")