Оболочка необязательного свойства, используемая в структуре Codable, завершается неудачно, если значение отсутствует - PullRequest
1 голос
/ 14 октября 2019

У меня есть struct со свойством Double, которое представляется как String в JSON, полученном из бэкэнда.

struct Test: Codable {
    @StringRepresentation
    var value: Double?
}

Вместо орудия init(from:)Я создал следующую оболочку свойств, которая использует LosslessStringConvertible для преобразования в String

@propertyWrapper
struct StringRepresentation<T: LosslessStringConvertible> {
    private var value: T?

    var wrappedValue: T? {
        get {
            return value
        }
        set {
            value = newValue
        }
    }
}

extension StringRepresentation: Codable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if container.decodeNil() {
            value = nil
        } else {
            let string = try container.decode(String.self)
            value = T(string)
        }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        if let value = value {
            try container.encode("\(value)")
        } else {
            try container.encodeNil()
        }
    }
}

. Это работает для

{
  "value": "12.0"
}

и

{
  "value": null
}

но происходит сбой при отсутствии свойства

{
}

с сообщением об ошибке

▿ DecodingError
  ▿ keyNotFound : 2 elements
    - .0 : CodingKeys(stringValue: "value", intValue: nil)
    ▿ .1 : Context
      - codingPath : 0 elements
      - debugDescription : "No value associated with key CodingKeys(stringValue: \"value\", intValue: nil) (\"value\")."
      - underlyingError : nil

Я предполагаю, что это происходит потому, что базовый StringRepresentation не является опциональным. Как я могу сделать это необязательным?

Редактировать: Кроме того, я должен кодировать объект как

{
"value": null
}

, то есть значение не может быть опущено.

1 Ответ

0 голосов
/ 14 октября 2019

Попробуйте изменить строку

let string = try container.decode(String.self)

На:

let string = try container.decodeIfPresent(String.self)

Как описано в документации, это будет декодировать значение данного типа для данного ключа, если оно присутствует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...