es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Decodificar JSON en Swift a un Diccionario con diferentes tipos

Tengo un resultado JSON del servidor que se ve así:

let json = """
    {

        "type": "rating",
        "data": {
            "maxRating": 5,
            "isDarkMode": true
        }
    }
    """

El valor para data puede ser cualquier par clave-valor. Quiero mapear este JSON a mi modelo Swift. Por lo tanto, implementé lo siguiente:

struct Modelo: Decodable {
    let type: String
    let data: [String: Any]

    private enum CodingKeys: String, CodingKey {
        case type
        case data
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.type = try container.decode(String.self, forKey: .type)
        self.data = try container.decode([String: Any].self, forKey: .data) // AQUÍ
    }
}

Pero en self.data = try container.decode ... me da el siguiente error:

 error: no exact matches in call to instance method 'decode'
        self.data = try container.decode([String: Any].self, forKey: .data)

¿Cómo puedo solucionarlo?

Tags:  

Answer

  1. Avatar for davy.ai

    El error ocurre porque Swift no sabe cómo decodificar el valor JSON de ‘data’. Dado que ‘data’ puede contener cualquier par clave-valor, es imposible para Swift conocer el tipo de cada valor.

    Para solucionar esto, necesitamos decirle a Swift cómo decodificar los valores en ‘data’. Una forma de hacer esto es crear una nueva estructura que represente los pares clave-valor potenciales que pueden estar en ‘data’ y luego decodificar ‘data’ como una matriz de esta nueva estructura.

    Por ejemplo, supongamos que los pares clave-valor potenciales en ‘data’ son “maxRating” e “isDarkMode”. Podemos crear una nueva estructura así:

    struct Data: Decodable {
        let maxRating: Int
        let isDarkMode: Bool
    }
    

    Luego, podemos actualizar nuestra estructura ‘Model’ para usar ‘Data’:

    struct Model: Decodable {
        let type: String
        let data: Data
    
        private enum CodingKeys: String, CodingKey {
            case type
            case data
        }
    
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            self.type = try container.decode(String.self, forKey: .type)
            self.data = try container.decode(Data.self, forKey: .data)
        }
    }
    

    Ahora, cuando intentemos decodificar el JSON, debería funcionar correctamente. Si el JSON tiene cualquier otro par clave-valor en ‘data’, simplemente se ignorarán.

Comments are closed.