Как я могу использовать [String: Any] ? как свойство в структуре, которое соответствует кодируемому

#swift #codable

#swift #codable

Вопрос:

У меня есть структура, которая соответствует кодируемому протоколу. У меня есть свойство типа [String: Any]? . Но кодируемый файл не позволяет мне его использовать. Сообщение об ошибке

does not conform to protocol 'Decodable

Комментарии:

1. Вы не можете иметь Any в своей структуре, если хотите соответствовать Codable

2. Можете ли вы предоставить больше информации о том, что вы хотите сделать с 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)