1

我正在从我的 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]改变整个父对象?

4

1 回答 1

4

您可以仅使用[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]

于 2020-08-19T12:31:07.007 回答