Estoy en el proceso de modificar un sistema para guardar una cola de solicitudes de API actualmente no enviadas a UserDefaults para que se vuelvan a enviar cuando la conexión del usuario lo permita.
Como algunas solicitudes de parches requieren la capacidad de enviar un valor NULO real a la API (y no simplemente ignorar el campo si es nulo opcional), esto significa que necesito la capacidad de codificar y decodificar valores nulos/NULOS de los valores predeterminados para ciertos campos .
Tengo el lado de codificación hacia abajo y felizmente puedo codificar solicitudes para enviar campos NULOS al servidor o codificarlos en valores predeterminados. Sin embargo, mi problema es que cuando se trata de decodificar solicitudes no enviadas guardadas, no puedo encontrar una manera de diferenciar entre un valor Nil real y el campo que simplemente no está allí.
Actualmente estoy usando decodeIfPresent para decodificar mis campos (todos los campos para estas solicitudes son opcionales), que devuelve cero si el campo está vacío O si el campo está configurado en Nil/NULL. Obviamente, esto no funciona para mis campos que pueden establecerse explícitamente en Nil, ya que no hay forma de diferenciar entre los dos casos.
¿Hay alguna metodología de decodificación que pueda implementar que permita diferenciar entre un campo que no está allí y un campo que realmente se establece en cero?
No hay forma, pero puedes agregar otra información para saberlo.
struct Root : Codable { let code : Int? let codeExists:Bool? init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) code = try values.decodeIfPresent(Int.self, forKey: .code) codeExists = values.contains(.code) } } De acuerdo con los documentos decodeIfPresent
Este método devuelve nil si el contenedor no tiene un valor asociado con la clave, o si el valor es nulo. La diferencia entre estos estados se puede distinguir con una llamada contains(_:).
Entonces decodificando
let str = """ { "code" : 12 } """da
Raíz (código: Opcional (12), existe código: Opcional (verdadero))
&&
Este
let str = """ { "code" : null } """da
Raíz (código: nil, codeExists: Opcional (verdadero))
y esto
let str = """ { } """da
Raíz (código: nil, codeExists: Opcional (falso))