Как сделать перехват ошибок в init (из decoder: Decoder) из структуры Codable? - PullRequest
0 голосов
/ 18 мая 2018
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. значения по умолчанию для каждого свойства.
  2. , делающего их все необязательными.

1 Ответ

0 голосов
/ 18 мая 2018

Вам не нужно do-catch в init(from decoder: Decoder), потому что оно уже помечено как 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.localizedDescription)

            return nil
        }
    }
}

let personData = """
{
    "name": 1,
    "gender": "male"
}
""".data(using: .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)
...