Swift codable, значение по умолчанию для свойства класса, когда ключ отсутствует в JSON

Как вы знаете, Codable - это новый элемент в Swift 4, поэтому мы перейдем к этому от старого процесса инициализации для моделей. Обычно мы используем следующий сценарий

class LoginModal
{    
    let cashierType: NSNumber
    let status: NSNumber

    init(_ json: JSON)
    {
        let keys = Constants.LoginModal()

        cashierType = json[keys.cashierType].number ?? 0
        status = json[keys.status].number ?? 0
    }
}

В JSON cashierType Ключ может отсутствовать, поэтому мы задаем значение по умолчанию как 0

Теперь сделать это с помощью Codable довольно просто, как показано ниже.

class LoginModal: Coadable
{    
    let cashierType: NSNumber
    let status: NSNumber
}

как упоминалось выше, ключи могут отсутствовать, но мы не хотим, чтобы переменные модели были необязательными. Итак, как мы можем добиться этого с помощью Codable.

Спасибо


person rinku khatri    schedule 10.11.2018    source источник
comment
Прежде всего, не используйте NSNumber в Swift, используйте Int, Double или Bool. Во-вторых, в этом случае вам нужно написать собственный инициализатор.   -  person vadian    schedule 10.11.2018
comment
@vadian На самом деле мы хотим использовать codable для управления ответом сервера. Итак, как уже упоминалось, мы уже используем настраиваемый инициализатор, есть ли способ справиться со всем этим с помощью codable?   -  person rinku khatri    schedule 10.11.2018
comment
Вы должны реализовать init(from decoder: и использовать decodeIfPresent, чтобы затронутые свойства могли назначать значения по умолчанию.   -  person vadian    schedule 10.11.2018


Ответы (1)


Используйте init(from decoder: Decoder), чтобы установить значения по умолчанию в вашей модели.

struct LoginModal: Codable {

    let cashierType: Int
    let status: Int

    enum CodingKeys: String, CodingKey {
        case cashierType = "cashierType"
        case status = "status"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.cashierType = try container.decodeIfPresent(Int.self, forKey: .cashierType) ?? 0
        self.status = try container.decodeIfPresent(Int.self, forKey: .status) ?? 0
    }
}

Чтение данных:

do {
        let data = //JSON Data from API
        let jsonData = try JSONDecoder().decode(LoginModal.self, from: data)
        print("\(jsonData.status) \(jsonData.cashierType)")
    } catch let error {
        print(error.localizedDescription)
    }
person Sateesh Yemireddi    schedule 10.11.2018
comment
Спасибо за ответ. Еще один вопрос: можно ли это сделать напрямую с помощью словаря или сначала преобразовать его в данные? - person rinku khatri; 10.11.2018
comment
Мы должны передать данные JSON, поступающие от API, в JSONDecoder. - person Sateesh Yemireddi; 10.11.2018
comment
Мы используем firebase оттуда, словарь приходит в ответ, поэтому можем ли мы использовать его напрямую или должны преобразовать его в данные. - person rinku khatri; 10.11.2018
comment
Вы можете отформатировать данные из словаря с помощью JSONSerialization и передать их в качестве аргумента JSONDecoder. - person Sateesh Yemireddi; 10.11.2018
comment
@Saleesh Почему В приведенном выше примере вы использовали структуру вместо класса. Есть ли какая-то конкретная причина? Поскольку я обычно рассматриваю struct как тип значения Datatype. Таким образом, прохождение через контроллеры представления будет создавать копии для этого каждый раз, и будет сложно обновить значения в одном экземпляре. - person Rahish; 11.04.2019
comment
@Rahish, Мы используем структуру для создания моделей для проекта, потому что мы не хотим каждый раз изменять его данные, получаемые с сервера. С другой стороны, если вы хотите изменить данные модели, вы можете рассматривать класс как тип для моделей. Без проблем..!! Это полностью зависит от требований проекта. Более того, экземпляры структур выделяются в стеке, а экземпляры классов размещаются в куче, иногда структуры могут быть значительно быстрее. - person Sateesh Yemireddi; 13.06.2019
comment
Привет, @Sateesh! Спасибо, что поделились своими знаниями о структурах и классах. Но наша основная забота - это кодирование. Мы хотим, чтобы модальное значение было необязательным. как упоминалось выше, ключи могут отсутствовать, но мы не хотим, чтобы переменные модели были необязательными. Итак, как мы можем добиться этого с помощью Codable. бывший. cashierType = json [keys.cashierType] .number ?? 0. Здесь мы устанавливаем 0 как значение по умолчанию, если не установим его на 0 и каким-то образом ключ может пропустить, тогда весь процесс завершится ошибкой. - person Rahish; 14.06.2019