Codable и CodingKeys

Я пытаюсь реализовать протокол с функциональностью, аналогичной тому, как 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?


person RPK    schedule 16.04.2019    source источник


Ответы (1)


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

Обрабатываются ли 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 свойствам _22 _ / _ 23_ по имени - получают автоматический синтез 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) для генерации исходного кода и передачи его компилятору.

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

person rob mayoff    schedule 16.04.2019
comment
Спасибо, это объяснение, которое я искал. - person RPK; 16.04.2019