#swift #codable
#swift #codable
Вопрос:
У меня есть структура, которая соответствует кодируемому протоколу. У меня есть свойство типа [String: Any]? . Но кодируемый файл не позволяет мне его использовать. Сообщение об ошибке
does not conform to protocol 'Decodable
Комментарии:
1. Вы не можете иметь
Any
в своей структуре, если хотите соответствовать Codable2. Можете ли вы предоставить больше информации о том, что вы хотите сделать с JSON? Существуют разные способы сделать это, которые имеют преимущества и недостатки.
3. У меня есть структура, как описано ниже. struct A: Codable { let a: Int let b: [String: Any] } Но выдает ошибку. Как я уже сказал в вопросе.
4. Замените
[String: Any]
на правильный тип, который соответствует вашему значению.[String: Any]
означает «сопоставление строк буквально любому типу, который когда-либо мог существовать». Невозможно преобразовать это в JSON (что бы вы сделали, если бы значение было CBPeripheral?) Поэтому измените свою структуру, чтобы использовать тип, который вы на самом деле имеете в виду. (Если вы не уверены, какой тип вы имеете в виду, это был бы хороший вопрос для StackOverflow .)5. Да, я не уверен в данных. Единственное, что я знаю, это то, что это будет словарь (JSON).
Ответ №1:
Используйте старый JSONSerialization
класс для преобразования между Data
и [String: Any]
, если необходимо. Data
является кодируемым. Вы также можете использовать другой формат, точно так же, как String
. Обратите внимание, что swift строго типизирован, поэтому обычно предпочтительнее использовать перечисление со связанными значениями Any
. Если целью является фактическая запись на сервер, а не в локальное хранилище, тогда вы также можете подумать о том, чтобы просто забыть о Codable и использовать JSONSerialization для всего этого.
Пример:
import UIKit
import PlaygroundSupport
struct A: Codable {
let a: Int
let b: [String: Any]
enum CodingKeys: String, CodingKey {
case a
case b
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
a = try values.decode(Int.self, forKey: .a)
let data = try values.decode(Data.self, forKey: .b)
b = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(a, forKey: .a)
let data = try JSONSerialization.data(withJSONObject: b, options: [])
try container.encode(data, forKey: .b)
}
}
Комментарии:
1. К сожалению, эта строка не расшифровывается:
values.decode(Data.self, forKey: .b)