首页 > 解决方案 > Decodable value String or Bool

问题描述

I'm currently working with a bad designed JSON Api... This returns always a value (eg. String, Int, Double...) or false(not null).

What is the best way to handle this with decodable, as Any is not supported by Codable?

A key can look like this:

{
    "key": "Test",
}

Or like this(I know, should be null instead of false):

{
    "key": false,
}

And this is not possible:

struct Object: Decodable {
    let key: Any?
}

标签: iosswiftcodable

解决方案


您可以创建一个通用包装类型,如果键的值为 ,则分配nil给一个Optionalfalse,否则它会解码该值。然后,您可以将它们包装在此包装器中,而不是存储实际类型。

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)
}

推荐阅读