Как предотвратить потерю ключей при декодировании/кодировании при изменении API?

Следующая ситуация: я использую несколько устройств, которые используют структуру данных. Если я сейчас раскрою ключи структуры для более новых версий, новые структуры кодируются, а затем синхронизируются. В результате синхронизации для декодирования используется старая структура данных. При последующей синхронизации с новыми устройствами новые ключи теряются. Как я могу предотвратить это?

введите здесь описание изображения

Используйте игровую площадку

import Foundation

struct OLD_API: Codable {
  var text: String
}

struct NEW_API: Codable {
  var text: String
  let value: Int
}

// Init data on device with NEW data struct
var newDevice = NEW_API(text: "Dog", value: 200)
let data = try! JSONEncoder().encode(newDevice)

// .. sync to other devices (new to old)

// modified data on device with OLD data struct
var oldDevice = try! JSONDecoder().decode(OLD_API.self, from: data)
oldDevice.text = "Cat"
let newData = try! JSONEncoder().encode(oldDevice)

// .. sync to other devices (old to new)

// decode data on device with NEW data struct
newDevice = try! JSONDecoder().decode(NEW_API.self, from: newData)
print(newDevice)

person Stefan    schedule 04.06.2021    source источник
comment
Это хороший вопрос, однако, пожалуйста, публикуйте код, а не изображения кода, который не доступен для поиска, не может быть скопирован/вставлен и плохо работает на мобильных устройствах или программах чтения с экрана.   -  person jnpdx    schedule 05.06.2021
comment
Конечно, они теряются, потому что старый API не знает о новых ключах. Вы можете объявить новые ключи необязательными. И я полностью согласен с jnpdx.   -  person vadian    schedule 05.06.2021
comment
Добавлен код @jnpdx.   -  person Stefan    schedule 05.06.2021
comment
К сожалению, необязательные ключи не являются решением. Я хочу избежать потери информации. @vadian   -  person Stefan    schedule 05.06.2021
comment
Это невозможно, если вы кодируете данные с помощью старого API, который просто отбрасывает новые ключи.   -  person vadian    schedule 05.06.2021
comment
Я согласен с vadian, новый ключ упадет. Я нахожу связанный с этим вопрос, он прочитал все ключи и значения, но еще не создал модель успешно. смотрите здесь: stackoverflow.com/questions/67403056/   -  person    schedule 05.06.2021
comment
Сейчас работаю со словарями. читать расшифровываю. когда я пишу, я работаю с многомерным словарем. Я думаю, что он должен сохранить исходный json и объединить новые данные. что ты думаешь?   -  person Stefan    schedule 05.06.2021


Ответы (1)


Оберните свой последний оператор декодирования с помощью do catch, и вы узнаете, что происходит.

  do {
   newDevice = try JSONDecoder().decode(NewApi.self, from: newData)
} catch {
   print(error)
}

ошибка будет примерно такой: keyNotFound(CodingKeys(stringValue: value, intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: Нет значения, связанного с ключом CodingKeys(stringValue: value, intValue: nil) (value) ., основная ошибка: ноль))

одна вещь, которую вы можете сделать, это создать собственный инициализатор декодера

 init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    text = try container.decode(String.self, forKey: .text)
    value = (try? container.decode(Int.self, forKey: .value) ) ?? 0
}

и укажите значение по умолчанию для свойства value, если оно не найдено

Я предлагаю вам переместить эту команду init в расширение структуры NewApi, чтобы не потерять инициализатор по умолчанию.

person Salah Amassi    schedule 04.06.2021
comment
Проблема не в том, что приведенный выше код дал сбой, а в том, что данные были потеряны. Если я создаю новое значение в своем приложении, которое вводит пользователь, оно удаляется при синхронизации со старым устройством. Так вот вопрос, как мне синхронизироваться со старыми устройствами не потеряв новый ключ со значениями. - person Stefan; 05.06.2021