问题描述
我正在从JSON REST API中检索复杂的嵌套对象。
DocumentDraft
- uuid: String
- schema: Schema // Very complicated object with many variations
- url: String
- values: [Value]
- successors: [String]
- predecessors: [String]
Value
- key: String
- val: String? OR [String]? // <-- This is the problem
struct Value<V: Decodable>: Decodable {
let key: String
let val: V?
}
...但是,即使如此,values
还是一个混合数组,所以我看不到声明V
是有帮助的。
但是,然后,当然,泛型类型会沿层次结构一直传播到DocumentDraft
对象,发布者,我的API调用等。这污染了否则非常干净易读的调用的整个链和对象。我只想在Value
级别上处理此问题,然后让JSONDecoder简单地以某种方式返回两者之一。
是否有另一种方式可以处理可选val
作为String
或[String]
的两种可能性,而无需更改整个父对象?
解决方法
您可以仅使用[String]
类型并手动实现init(from:)
协议的Decodable
功能,如下所示:
struct Value: Decodable {
let key: String
let val: [String]?
enum CodingKeys: String,CodingKey {
case key,val
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
key = try container.decode(String.self,forKey: .key)
do {
if let string = try container.decodeIfPresent(String.self,forKey: .val) {
val = [string]
} else {
val = nil
}
} catch DecodingError.typeMismatch {
val = try container.decodeIfPresent([String].self,forKey: .val)
}
}
}
成功解码为String
值时,请创建仅包含一个元素的字符串数组。解码为String
值失败时,请尝试解码为[String]