Swift Decodable - como evitar o tipo genérico?
Estou recuperando um objeto aninhado complexo de minha API JSON REST.
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
Suponho que a maneira adequada de lidar com isso seja introduzir um tipo genérico.
struct Value<V: Decodable>: Decodable {
let key: String
let val: V?
}
... mas mesmo assim, values
poderia ser uma matriz mista, então não vejo como declarar o V
que ajudaria.
Mas então, é claro que o tipo genérico se propaga por toda a hierarquia, para o DocumentDraft
objeto, para o editor, para minhas chamadas de API, etc. poluindo toda a cadeia de chamadas e objetos de outra forma muito limpos e legíveis. Eu gostaria de lidar com isso apenas no nível de Value
e deixar o JSONDecoder simplesmente retornar um dos dois de alguma forma.
Existe outra maneira de lidar com as duas possibilidades do opcional val
como um String
ou outro [String]
sem alterar todo o objeto pai?
Respostas
Você pode conseguir isso usando apenas o [String]
tipo e implementando manualmente a init(from:)
função do Decodable
protocolo como este:
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)
}
}
}
Quando a decodificação para String
valor for bem-sucedida, crie uma matriz de strings com apenas um elemento. Quando a decodificação para o String
valor falha, tente decodificar como[String]