Codable и CodingKeys - PullRequest
       12

Codable и CodingKeys

0 голосов
/ 16 апреля 2019

Я пытаюсь реализовать протокол с функциональностью, аналогичной тому, как Codable использует перечисление CodingKeys.

С Codable и CodingKeys, если вы не реализуете регистр в перечислении CodingKeys для каждого свойства объекта Codable, это вызывает ошибку компилятора, заявляющую, что объект не соответствует протокол.

Я просмотрел документацию, и единственное, что я могу найти в связи с протоколом Codable (Encodable и Decodable), - это требование реализовать функции func encode(to encoder: Encoder) и init(from decoder: Decoder).

Самое близкое, что я получил, это определение протокола следующим образом:

protocol TestProtocol {
    associatedType Keys: CodingKey
}

Для этого требуется, чтобы у разработчика было свойство Keys, соответствующее CodingKey, но оно не обязывает применять регистр для всех свойств. Кроме того, вы не можете объявить свойство Keys как личное как вы можете с помощью Codable.

Обрабатываются ли Codable и CodingKeys на более глубоком уровне, чем то, что раскрывается через API?

Если нет, есть ли способ реализовать функциональность CodingKeys вне Codable?

1 Ответ

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

Вы задаете два вопроса.Я отвечу на них не по порядку.

Codable и CodingKeys обрабатываются на более глубоком уровне, чем то, что раскрывается через API?

Да, компилятор Swiftзнает о протоколах Encodable, Decodable и CodingKey и имеет специальный код для них.

Компилятор может синтезировать CodingKey -совместимый enum с именем CodingKeys, init(from:) инициализатор и метод encode(to:), если выполняются некоторые условия.Условия прописаны в SE-0166 :

Encodable & Decodable. Также могут быть автоматически синтезированы для определенных типов:

  1. Типы, соответствующие Encodable, все свойства которых Encodable, получают автоматически сгенерированные String -обеспеченные CodingKey enum сопоставления свойств с именами дел.Аналогично для Decodable типов, чьи свойства имеют все Decodable
  2. Типы, попадающие в (1), и типы, которые вручную предоставляют CodingKey enum (с именем CodingKeys, напрямую или через typealias), случаи которых отображают свойства 1-в-1 в Encodable / Decodable по имени - получают автоматический синтез init(from:) и encode(to:) в зависимости от ситуации, используя эти свойства и ключи
  3. Типы, которыеНи в (1), ни (2) не потребуется предоставлять пользовательский тип ключа, если это необходимо, и предоставлять свои собственные init(from:) и encode(to:), в зависимости от ситуации

Обратите внимание, что CodingKey -поддерживаемый тип обычно не имеет с именем CodingKeys или даже enum, если вы не полагаетесь на соответствие, синтезированное компилятором.

Кроме того, обратите внимание, чтоТип CodingKeys, соответствующий CodingKey, должен иметь регистр для каждого члена включающего его типа, если вы полагаетесь на компилятор, чтобы синтезировать init(from:) или encode(to:).

Если вы вручнуюреализуя init(from:) и encode(to:), вы можете использовать любое имя для вашего CodingKey -подобного типа, и он должен иметь только те случаи, которые вас волнуют.Вам даже не нужен CodingKey -совместимый тип, если вы используете для хранения только контейнер с одним значением или контейнер без ключа.

Если нет, есть ли способ реализоватьФункциональность CodingKeys вне Codable?

Если под «функциональностью» вы подразумеваете способ, которым компилятор автоматически синтезирует реализации, то единственный способ - использовать генератор кода (например, Sourcery или gyb) для генерацииисходный код и передайте его компилятору.

Если под «функциональностью» вы подразумеваете способ, которым компилятору требуется ключевой элемент для каждого Encodable / Decodable члена включающего типа, то единственныйпуть заключается в запуске отдельной программы, которая анализирует ваш исходный код и выявляет ошибки, если какой-либо случай отсутствует.Вы не можете заставить стандартный компилятор Swift сделать это за вас.

...