如何从 Codable 结构中捕获 init(来自解码器:解码器)中的错误?

Posted

技术标签:

【中文标题】如何从 Codable 结构中捕获 init(来自解码器:解码器)中的错误?【英文标题】:How to do-catch error in init(from decoder:Decoder) from a Codable struct? 【发布时间】:2018-05-18 04:36:17 【问题描述】:
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)")
        
    

从上面的代码来看,它不会编译,因为它会报错,

从初始化程序返回而不初始化所有存储的属性。

我想抛出一些错误,但是如果没有,我该怎么做,

    为每个属性设置默认值。 将它们全部设为可选。

【问题讨论】:

请注意,对于此数据结构,自定义初始化程序是多余的。 【参考方案1】:

您不需要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)

【讨论】:

那么如何知道异常呢? @Nuibb 如果您在调用周围使用do-catch 来解码数据,则无论解码是什么都可以被告知异常。我将在我的答案中添加一个示例。 @TylerTheCompiler 它没有去捕捉范围。 @TylerTheCompiler 好的,它确实成功了。但是需要编辑 Swift Error 断点才能继续,而不是卡在那里。 @hasan 我不确定你在说什么。

以上是关于如何从 Codable 结构中捕获 init(来自解码器:解码器)中的错误?的主要内容,如果未能解决你的问题,请参考以下文章

如何从具有多个值的 Codable 结构中获取一个值?

swift 中使用Codable进行数据解析

CoreData 和 Codable 类编译器错误:在从初始化程序返回之前,未在所有路径上调用“self.init”

同时从 API 调用和模型文件中解码 Codable 结构

如何从 iOS Swift Codable 中的 API 响应通知或打印模型类上缺少的密钥?

Swift - 如何使这个结构符合 Codable?