У меня есть структура, показанная ниже:
struct ItemList: Decodable {
var items: [UUID: Int]
}
Я получаю следующие данные JSON:
{
"items": {
"b4f8d2fa-941f-4f9a-a98c-060bbd468575": 418226428193,
"81efa661-4845-491b-8bf4-06d5dff1d5f8": 417639857722
}
}
Теперь, когда я пытаюсь расшифровать приведенные выше данные, я получаю интересную ошибку. Ясно, что я не декодирую массив, и ясно, что все указывает на словарь.
try JSONDecoder().decode(ItemList.self, from: data)
// typeMismatch(
// Swift.Array<Any>,
// Swift.DecodingError.Context(
// codingPath: [
// CodingKeys(stringValue: "items", intValue: nil)
// ],
// debugDescription: "Expected to decode Array<Any> but found a dictionary instead.",
// underlyingError: nil
// )
// )
Итак, я пошел поэкспериментировать и изменил [UUID: Int]
на [String: Int]
, что делает эту работу, почти заставляя меня думать, что ошибка связана не с массивом / словарем, а с UUID / String. Итак, я также провел следующий тест, который никогда не терпит неудач.
let list = try JSONDecoder().decode(ItemList.self, from: data)
for (key, value) in list.items {
// This will never print `nil`
print(UUID(uuidString: key))
}
Итак, у меня вопрос: почему я получаю эту странную ошибку typeMismatch
при декодировании и почему она работает, когда я меняю UUID
на String
, поскольку она явно может быть правильно декодирована?
Decodable
, не имеет большого значения, потому что JSON поддерживает толькоString
как ключ словаря. ОднакоDecodable
не может обеспечить, чтобы тип ключа мог декодироватьString
. Поэтому у них был выбор - попытаться декодироватьString
в данный тип и выбросить исключение, если это невозможно, или использовать другой способ хранения данных при обнаружении ключа, отличного от String. Первый вариант был бы проблематичным при кодировании, поэтому они выбрали второй. - person Sulthan   schedule 14.04.2021