Как закодировать реализацию свойства протокола по умолчанию в словарь - PullRequest
0 голосов
/ 25 апреля 2019

Я хочу сделать словарь из кодируемой структуры со свойством реализации по умолчанию.

struct MyStruct: MyStructProtocol {
    var value: String
}

Структура реализует протокол.Этот протокол имеет две переменные.Одна переменная имеет реализацию по умолчанию.

protocol MyStructProtocol: Encodable {
    var defaultValue: String { get }
    var value: String { set get }
}

extension MyStructProtocol {
    var defaultValue: String { return "my-default-value" }
}

Для этого я использую это Encodable расширение от Как я могу использовать Codable Swift для кодирования в словарь? :

extension Encodable {
    var asDictionary: [String: Any]? {
        guard let data = try? JSONEncoder().encode(self) else { return nil }
        return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
    }
}

Поэтому, когда я создаю экземпляр структуры и "кодирую" ее в словарь:

let myStruct = MyStruct(value: "my-value")
let myStructDictionary = myStruct.asDictionary

, тогда defaultValue не включается:

["value": "my-value"]

Номне нужно (включая значение по умолчанию):

["defaultValue": "my-default-value", "value": "my-value"]

Ответы [ 3 ]

2 голосов
/ 25 апреля 2019

Синтезированный кодировщик рассматривает только элементы в структуре, а не какие-либо свойства в расширении протокола или вычисляемые свойства.

Вы должны написать собственный инициализатор. И я предпочел бы, чтобы структура приняла Encodable, а не протокол.

struct MyStruct: MyStructProtocol, Encodable {
    var value: String

    private enum CodingKeys: String, CodingKey { case value, defaultValue }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(value, forKey: .value)
        try container.encode(defaultValue, forKey: .defaultValue)
    }
}

protocol MyStructProtocol { ...
0 голосов
/ 25 апреля 2019

Это потому, что значение по умолчанию для defaultValue было реализовано в расширении для протокола, что означает, что это вычисляемое свойство .

struct MyStruct: MyStructProtocol {
    var value: String

    enum CodingKeys: String, CodingKey {
        case value
        case defaultValue = "my-default-value"
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(value, forKey: .value)
        try container.encode(defaultValue, forKey: .defaultValue)
    }
}
0 голосов
/ 25 апреля 2019

Encodable не распознает вычисленные свойства. Чтобы это исправить, переопределите функцию encode(to:), как показано в официальной документации https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types

РЕДАКТИРОВАТЬ: возможное решение проблемы: Как использовать вычисляемое свойство в кодируемой структуре (swift)

...