Swift 4.2 - декодирование JSON, где один и тот же ключ отличается - PullRequest
0 голосов
/ 06 марта 2019

Я декодирую объект, используя следующую модель

struct ACDeviceLastData {
    var DA: ACDeviceLastDataBody = ACDeviceLastDataBody()
}

struct ACDeviceLastDataBody {
    var amOn: Bool = false
    var enabledZones: [Int] = []
    var fanSpeed: Int = 0
    var mode: Int = 0
    var tempTarget: Float = 0.00
}

extension ACDeviceLastData: Decodable {
        init(from decoder: Decoder) throws {
            //Create Container
            let container = try decoder.container(keyedBy: ACDeviceCodingKeys.self)

        //Decode Data
        DA = try container.decodeIfPresent(ACDeviceLastDataBody.self, forKey: .DA) ?? ACDeviceLastDataBody()
    }
}

extension ACDeviceLastDataBody: Decodable {
    init(from decoder: Decoder) throws {
        //Create Container
        let container = try decoder.container(keyedBy: ACDeviceCodingKeys.self)

        //Decode Data
        amOn = try container.decodeIfPresent(Bool.self, forKey: .amOn) ?? false
        enabledZones = try container.decodeIfPresent([Int].self, forKey: .enabledZones) ?? []
        fanSpeed = try container.decodeIfPresent(Int.self, forKey: .fanSpeed) ?? 0
        mode = try container.decodeIfPresent(Int.self, forKey: .mode) ?? 0
        tempTarget = try container.decodeIfPresent(Float.self, forKey: .tempTarget) ?? 0.00
    }
}

Проблема в том, что значение DA не всегда одного и того же типа.Иногда это может быть в формате массива целых чисел, а иногда в формате ACDevieLastDataBody.Я пытался сделать do-try-catch, но не мог понять, как заставить это работать (если это даже правильно)

Мой вопрос здесь, как мне поступитьо декодировании их без броска декодера, когда это массив целых чисел.Любая помощь очень ценится.Заранее благодарю.

Ответы [ 2 ]

1 голос
/ 06 марта 2019

Прежде всего, вы должны выбрать способ хранения данных. Для простоты давайте сохраним массив Int как отдельное свойство:

struct ACDeviceLastData {
   var DA: ACDeviceLastDataBody = ACDeviceLastDataBody()
   var DAasInts: [Int] = []
}

extension ACDeviceLastData: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: ACDeviceCodingKeys.self)

        if let ints: [Int] = try? (container.decodeIfPresent([Int].self, forKey: .DA) ?? []) {
            // will pass here when `DA` is null or an array of ints
            DA = ACDeviceLastDataBody()
            DAasInts = ints
        } else {
            // null is already handled above
            DA = try container.decode(ACDeviceLastDataBody.self, forKey: .DA)
            DAasInts = []
        }
    }
}

Возможно, вы захотите представить ваши данные по-другому, например, создать ACDeviceLastDataBody из массива целых.

0 голосов
/ 06 марта 2019

Вам нужно расположить типы в init(from decoder: Decoder)

Это простое преобразование, помните, что типы могут не совпадать, так что совместимость зависит от вас, ваше бремя.

Я не вижу JSON, но JSON to Code очень легко сделать, поскольку типы JSON всегда просты на атомарном уровне.

Надеюсь, это помогло ...

У тебя хороший день!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...