How can I create a swift structure so I can decode a json

0

Through an API Rest I receive a json with the following structure:

{
    "estado": 1,
    "datos": [
        {
            "idContacto": "1",
            "primerNombre": "Juan Jose",
            "primerApellido": "Villasetin",
            "telefono": "8899765444",
            "correo": "[email protected]",
            "idUsuario": "1"
        },
        {
            "idContacto": "3",
            "primerNombre": "Ravello",
            "primerApellido": "Manzanillo",
            "telefono": "9999992344",
            "correo": "[email protected]",
            "idUsuario": "1"
        }
    ]
}

In swift I have the following structures:

struct Contacto : Codable {
    let estado : Int
    let datos : Datos
}

struct Datos : Codable {
    let primerNombre : String
    let telefono : String
}

When trying to decode the json with the following instruction:

self.contactos = try JSONDecoder().decode([Contacto].self, from: data!)

The error is triggered:

  

The data could not be read because it is not in the correct format.

    
asked by Pillo 28.05.2018 в 04:04
source

1 answer

0

To decode a JSON in swift there are many options and all valid, you can use an external object such as SWiftyJSON or the Jsondecoder that you use. Or you can decode it by hand, so you know in which line it can fail and what is happening. If the JSOn is long and complicated you will have to spend a long time, it is a heavy task and you have to make a decoder for each structure. How do I do it, because in the struct I create the decoder for that structure in particular. For the JSON you pass, let's imagine that the fields of first name, first surname and telephone are obligatory and the others can come to null or fillings, but without the obligatory fields I can not accept that data as valid

Within the definition of the struct, I create the decoder

struct Datos {
   //la definición de tus datos
   .....

   static func decodeData(json: [String: AnyObject]) -> Datos? {
        //me aseguro de los datos que tiene que ser obligatorios en caso contrario devuelvo nil
        guard let nom = json["primerNombre"] as? String,
              let ape = json["primerApellido"] as? String,
              let tlf = json["telefono"] as? String
        else {
              //falta algún dato obligatorio
              return nil
        }
        //ahora los datos que si vienen nulo no pasaría nada
        let idContacto = json["idContacto"] as? Int
        let mail = json["correo"] as? String
        let idUser = json["idUsuario"] as? Int

        //ya tengo los datos, creo el modelo
        let m = Datos(id:idContacto, nombre: nom, apellido: ape, telefono: tlf, mail: mail, user: idUser);
        return m
   }
}

But according to your JSON, the data goes inside an array, so you have to go through that array to decode each data. We will need another method, within the struct

static func decodeJSON(json: [String: AnyObject]) -> [Datos] {
   //genero el listado de los datos
   var arr: [Datos] = []
   //me recorro el array de datos
   guard let datos = json["datos"] as? [Dictionary<String, AnyObject>]
   else {
       //no viene datos, o el json esta mal, devuelvo el array vacío
       return arr
   }

   //me recorro todos los datos que me vienen
   for d in datos {
      if let dat = Datos.decodeData(json: d) {
           //el datos es valido
           arr.append(dat)
       } else {
          //el dato no es valido, aquí haces lo que necesites
       }
   return arr
}

Trying json in swift is pretty heavy, that's why there are many tools or you work it by hand. This is an option, mine, you can answer many more options and surely will also serve you. To taste the colors.

    
answered by 28.05.2018 / 07:45
source