可解码值String或Bool

时间:2018-10-16 13:21:03

标签: ios swift codable

我目前正在使用设计错误的JSON API ... 始终返回一个值(例如String,Int,Double ...)或false(不为null)。

用Codable不支持Any的最佳方式是什么?

键可能看起来像这样:

{
    "key": "Test",
}

或者这样(我知道,应该为null而不是false):

{
    "key": false,
}

这是不可能的:

struct Object: Decodable {
    let key: Any?
}

2 个答案:

答案 0 :(得分:2)

您可以创建一个通用包装类型,如果键的值为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)
}

答案 1 :(得分:0)

在相同的情况下,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块,在其中进行转换