Декодируемое значение String или Bool - PullRequest
0 голосов
/ 16 октября 2018

В настоящее время я работаю с плохо спроектированным JSON Api ... Это всегда возвращает значение (например, String, Int, Double ...) или false (не ноль).

Что такоелучший способ справиться с этим с помощью decodable, так как Any не поддерживается Codable?

Ключ может выглядеть так:

{
    "key": "Test",
}

Или вот так (я знаю, должно быть null вместоfalse):

{
    "key": false,
}

И это невозможно:

struct Object: Decodable {
    let key: Any?
}

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

У меня такая же ситуация, когда ID может быть Int или String

class MyClass: Codable {
    let id: Int?
    required init(from decoder: Decoder) throws {
       let values = try decoder.container(keyedBy: CodingKeys.self)

       do {
           let stringId = try values.decodeIfPresent(String.self, forKey: .id)
            id = Int(stringId ?? "0")

          } catch {
             id = try values.decodeIfPresent(Int.self, forKey: .id)

         }
    }

  }

Внутри required init(from decoder: Decoder) throws У меня есть другой блок do try, в который я конвертирую его

0 голосов
/ 16 октября 2018

Вы можете создать общий тип оболочки, который присваивает nil значению Optional, если значение для ключа равно false, в противном случае оно декодирует значение.Затем вместо хранения реальных типов вы можете обернуть их в эту оболочку.

struct ValueOrFalse<T:Decodable>: Decodable {
    let value:T?

    public init(from decoder:Decoder) throws {
        let container = try decoder.singleValueContainer()
        let falseValue = try? container.decode(Bool.self)
        if falseValue == nil {
            value = try container.decode(T.self)
        } else {
            value = nil
        }
    }
}

struct RandomJSONStruct: Decodable {
    let anInt:ValueOrFalse<Int>
    let aString:ValueOrFalse<String>
}

let noValueJson = """
{
    "anInt": false,
    "aString": "Test"
}
"""

do {
    print(try JSONDecoder().decode(RandomJSONStruct.self, from: noValueJson.data(using: .utf8)!))
} catch {
    print(error)
}
...