Значение по умолчанию для необязательного ключа - PullRequest
0 голосов
/ 18 июня 2019

У меня есть объект JSON, у которого всегда есть text, а иногда есть ключ format, а когда его нет, я хочу использовать регистр .regular для моего SubStep.Format перечисления.

Я знаю, что мне нужно переопределить init в SubStep, но как мне сделать так, чтобы я мог определить ключ форматирования, если он равен нулю, использовать .regular, а затем просто декодировать клавишу text это всегда там?

Спасибо

struct SubStep: Decodable {
    enum Format: String, Decodable {
        case bold = "bold"
        case regular = "regular"

        init(from decoder: Decoder) {
            do {
                let label = try decoder.singleValueContainer().decode(String.self)
                self = Format(rawValue: label) ?? .regular
            } catch {
                self = .regular
            }
        }
    }

    let format: SubStep.Format
    let text: String

    init(from decoder: Decoder) throws {
       // something in here
    }
}

Ответы [ 2 ]

2 голосов
/ 18 июня 2019

Вам не нужно создавать пользовательский метод init(from:) для Format, вам нужен только один для SubStep.Вам нужно использовать container.decodeIfPresent(_:forKey:) для декодирования ключа, который может отсутствовать в вашем JSON, и в этом случае он возвращает nil.

struct SubStep: Decodable {
    enum Format: String, Decodable {
        case bold
        case regular
    }

    let format: SubStep.Format
    let text: String

    private enum CodingKeys: String, CodingKey {
        case text, format
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.text = try container.decode(String.self, forKey: .text)
        self.format = try container.decodeIfPresent(Format.self, forKey: .format) ?? .regular
    }
}

Не имеет отношения к вашей проблеме, но вам не нужнопредоставьте String rawValue для ваших enum кейсов, если их rawValue будет точно соответствовать названию кейса, компилятор автоматически создаст их для вас.

1 голос
/ 19 июня 2019

Как альтернативное решение, вам не нужно вставлять значение по умолчанию во время синтаксического анализа - вы можете использовать вместо него вычисляемое свойство.

struct SubStep: Decodable {
    enum Format: String, Decodable {
        case bold
        case regular
    }

    private let formatOptional: Format?
    let text: String

    private enum CodingKeys: String, CodingKey {
        case formatOptional = "format"
        case text
    }

    var format: Format {
        return formatOptional ?? .regular
    }
}
...