Swift - есть ли способ различать поле, отсутствующее или поле, равное nil / null, при декодировании необязательного значения Codable - PullRequest
0 голосов
/ 13 февраля 2019

Необходимая функциональность

Я нахожусь в процессе модификации системы, чтобы сохранить очередь неотправленных в данный момент запросов API к UserDefaults, которые будут повторно отправлены, когда соединение пользователя позволяет.

Поскольку для некоторых запросов на исправление требуется возможность отправлять фактическое значение NULL в API (а не просто игнорировать поле, если оно является необязательным nil), это означает, что мне нужна возможность кодировать и декодировать значения nil / NULL из значений по умолчанию для определенных полей.

Проблема

У меня есть сторона кодирования, и я могу успешно кодировать запросы на отправку на сервер пустых полей или кодировать их по умолчанию.Однако моя проблема заключается в том, что когда дело доходит до декодирования сохраненных неотправленных запросов, я не могу найти способ провести различие между фактическим значением Nil и полем, просто отсутствующим там.

В настоящее время я использую decodeIfPresent для декодирования моих полей (все поля для этих запросов являются необязательными), которое возвращает nil, если поле пустое ИЛИ, если поле установлено в Nil / NULL.Очевидно, что это не работает для моих полей, которые могут быть явно установлены на ноль, так как я не могу провести различие между этими двумя случаями.

Вопрос

Существует ли какая-либо методология декодирования, которую ямог бы реализовать, что позволило бы провести различие между полем, которого там нет, и полем, фактически установленным в ноль?

1 Ответ

0 голосов
/ 13 февраля 2019

Нет способа, но вы можете добавить другую информацию, чтобы знать, что

struct Root : Codable {

    let code : Int?
    let codeExists:Bool?

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self) 
        code = try values.decodeIfPresent(Int.self, forKey: .code)
        codeExists =  values.contains(.code)

    }
}

Согласно документации decodeIfPresent

Этот метод возвращает ноль, если контейнер неиметь значение, связанное с ключом, или если значение равно нулю.Различие между этими состояниями можно различить с помощью вызова has (_ :).

Таким образом, декодирование

let str = """
{
  "code" : 12
}
"""

дает

Root (код: Необязательно (12), codeExists: Необязательно (true))

&&

Этот

let str = """
{
  "code" : null
}
"""

дает

Root(код: ноль, codeExists: необязательный (true))

, и этот

let str = """
{

}
"""

дает

Root (код: ноль, codeExists:Необязательный (false))

...