如何从 Codable 结构中捕获 init(from decoder:Decoder) 中的错误?
How to do-catch error in init(from decoder:Decoder) from a Codable struct?
let jsonString = """
{
"name":1,
"gender":"male",
}
"""
struct Person: Codable {
var name: String
var gender: String
public init(from decoder: Decoder) throws {
do {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
gender = try container.decode(String.self, forKey: .gender)
} catch {
print("XXXXXX \(error)")
}
}
}
从上面的代码来看,它不会编译,因为它会抱怨,
Return from initializer without initializing all stored properties.
我想抛出一些错误,但如果没有,我该怎么做,
- 为每个属性设置默认值。
- 将它们全部设为可选。
您不需要 init(from decoder: Decoder)
中的 do-catch
,因为它已被标记为 throws
。所以就这样做:
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
gender = try container.decode(String.self, forKey: .gender)
}
无论解码如何,都可以使用 do-catch
查看上述 init(from:)
方法中抛出的任何异常,如下例所示:
struct Person: Codable {
var name: String
var gender: String
// Note: This is not a very good example because this init method
// is not even necessary in this case, since the automatically-
// synthesized `init(from:)` method does exactly the same thing. I've
// left it here to illustrate that you don't need to have a `do-catch`
// in this method and can instead just use `try`, since the method
// is marked as `throws`.
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
gender = try container.decode(String.self, forKey: .gender)
}
}
class PersonDecoder {
func person(decodedFrom data: Data) -> Person? {
do {
// The `JSONDecoder.decode(_:from:)` method calls
// `Person.init(from:)`, which can throw, which is why
// `JSONDecoder.decode(_:from:)` also throws.
let person = try JSONDecoder().decode(Person.self, from: data)
return person
} catch {
// Inspect any thrown errors here.
print(error)
return nil
}
}
}
let personData = Data("""
{
"name": 1,
"gender": "male"
}
""".utf8)
let personDecoder = PersonDecoder()
// Prints: "The data couldn’t be read because it isn’t in the correct format."
// and `person` is nil.
let person = personDecoder.person(decodedFrom: personData)
let jsonString = """
{
"name":1,
"gender":"male",
}
"""
struct Person: Codable {
var name: String
var gender: String
public init(from decoder: Decoder) throws {
do {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
gender = try container.decode(String.self, forKey: .gender)
} catch {
print("XXXXXX \(error)")
}
}
}
从上面的代码来看,它不会编译,因为它会抱怨,
Return from initializer without initializing all stored properties.
我想抛出一些错误,但如果没有,我该怎么做,
- 为每个属性设置默认值。
- 将它们全部设为可选。
您不需要 init(from decoder: Decoder)
中的 do-catch
,因为它已被标记为 throws
。所以就这样做:
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
gender = try container.decode(String.self, forKey: .gender)
}
无论解码如何,都可以使用 do-catch
查看上述 init(from:)
方法中抛出的任何异常,如下例所示:
struct Person: Codable {
var name: String
var gender: String
// Note: This is not a very good example because this init method
// is not even necessary in this case, since the automatically-
// synthesized `init(from:)` method does exactly the same thing. I've
// left it here to illustrate that you don't need to have a `do-catch`
// in this method and can instead just use `try`, since the method
// is marked as `throws`.
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decode(String.self, forKey: .name)
gender = try container.decode(String.self, forKey: .gender)
}
}
class PersonDecoder {
func person(decodedFrom data: Data) -> Person? {
do {
// The `JSONDecoder.decode(_:from:)` method calls
// `Person.init(from:)`, which can throw, which is why
// `JSONDecoder.decode(_:from:)` also throws.
let person = try JSONDecoder().decode(Person.self, from: data)
return person
} catch {
// Inspect any thrown errors here.
print(error)
return nil
}
}
}
let personData = Data("""
{
"name": 1,
"gender": "male"
}
""".utf8)
let personDecoder = PersonDecoder()
// Prints: "The data couldn’t be read because it isn’t in the correct format."
// and `person` is nil.
let person = personDecoder.person(decodedFrom: personData)