我目前正在使用设计错误的JSON API ... 始终返回一个值(例如String,Int,Double ...)或false(不为null)。
用Codable不支持Any的最佳方式是什么?
键可能看起来像这样:
{
"key": "Test",
}
或者这样(我知道,应该为null而不是false):
{
"key": false,
}
这是不可能的:
struct Object: Decodable {
let key: Any?
}
答案 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块,在其中进行转换