使用结构

时间:2019-05-27 22:37:01

标签: json swift decode

我一直在尝试为必须解码JSON的应用程序解码数组。

我只是无法用我的实际结构和以前尝试过的其他结构对其进行解码。

这是我的最新结构:

struct peticion: Decodable{
    let datos_conexion: datos_conexion
    let estado_lanzamiento: estado_lanzamiento
    let usuario: usuario
}

struct datos_conexion: Decodable {
    let conexion: datosConexion
}

struct datosConexion: Decodable{
    let datos_conexion: String
}

struct estado_lanzamiento: Decodable{
    let tiempo_restante: String
    let etapa_actual: String
}

struct usuario: Decodable {
    let Id: Int
    let Nombre: String
    let Password: String
    let Imagen: String
    let Puesto: String
    let Departamento: String
}

Request中的JSON完整示例

[
    {
        "datos_conexion": {
            "conexion": "2019-05-27 17:05:45"
        }
    },
    {
        "estado_lanzamiento": {
            "tiempo_restante": 240,
            "etapa_actual": "Configuracion"
        }
    },
    {
        "usuario": [
            {
                "Id": "4",
                "Nombre": "This is the Name",
                "Email": "email@gmail.com",
                "Password": "1234",
                "Imagen": "default.jpg",
                "Puesto": "",
                "Departamento": "Etapa Final"
            }
        ]
    }
]

解码代码

URLSession.shared.dataTask(with: url2) { (data, resp, err) in
    guard let data = data else{return}
    let dataAsString = String(data: data, encoding: .utf8)
//      print(dataAsString)
    do {
        let JSONDATA = try JSONDecoder().decode([peticion].self, from: data)
//     print(data)
    } catch let jsonErr {
        print("cant decode", jsonErr)
    }

尝试执行此操作时出错:

  

typeMismatch(Swift.Array,Swift.DecodingError.Context(codingPath:[],debugDescription:“预期对Array进行解码,但找到了一个字典。”,底层错误:无))

     

typeMismatch(Swift.Array,Swift.DecodingError.Context(codingPath:[],debugDescription:“预期用于解码字典,但找到了一个Array。”,底层错误:无))

2 个答案:

答案 0 :(得分:0)

根据您的JSON,您将收到一个[[String: Any]],其中Array包含DictionariesAny值和String键。这很棘手,因为字典包含Any的值,该值不可解码。另外,容器是Array,通常我们将Dictionary作为容器。

通常,我们会简化此响应。。但是,在这种情况下我们无法做到。

一种解码方法是:


struct Peticion: Decodable{
    let datosConexion: DatosConexion
    let estadoLanzamiento: EstadoLanzamiento
    let usuario: [Usuario]

    init(from decoder : Decoder) throws {
        //unkeyed because we are getting an array as container
        var unkeyedContainer = try decoder.unkeyedContainer()
        let datosConexionWrapper = try unkeyedContainer.decode(DatosConexionWrapper.self)

        let estadoLanzamientoWrapper = try unkeyedContainer.decode(EstadoLanzamientoWrapper.self)
        let usuarioWrapper = try unkeyedContainer.decode(UsuarioWrapper.self)

        datosConexion = datosConexionWrapper.datosConexion
        estadoLanzamiento = estadoLanzamientoWrapper.estadoLanzamiento
        usuario = usuarioWrapper.usuario

    }
}


//use wrappers to handle the outer dictionary
struct DatosConexionWrapper: Decodable{
   let datosConexion: DatosConexion

   enum CodingKeys: String, CodingKey{
      case datosConexion = "datos_conexion"
   }
}

struct DatosConexion: Decodable{
   let conexion: String
}



struct EstadoLanzamientoWrapper: Decodable{
  let estadoLanzamiento: EstadoLanzamiento

  enum CodingKeys: String, CodingKey{
      case estadoLanzamiento = "estado_lanzamiento"
   }
}

struct EstadoLanzamiento: Decodable{
   let tiempoRestante: Int
   let etapaActual: String

   enum CodingKeys: String, CodingKey {
        case tiempoRestante = "tiempo_restante"
        case etapaActual = "etapa_actual"
    }
}

struct UsuarioWrapper: Decodable{
  let usuario: [Usuario]

}

struct Usuario: Decodable{
   let id: String
   let nombre: String
   let email: String
   let password: String
   let imagen: String
   let puesto: String
   let departamento: String


   enum CodingKeys: String, CodingKey {
        case id = "Id"
        case nombre = "Nombre"
        case email = "Email"
        case password = "Password"
        case imagen = "Imagen"
        case puesto = "Puesto"
        case departamento = "Departamento"
   }
}

解码代码//我只将解码类型更改为我的Peticion结构


URLSession.shared.dataTask(with: url2) { (data, resp, err) in
    guard let data = data else{return}
    let dataAsString = String(data: data, encoding: .utf8)
//      print(dataAsString)
    do {
        let JSONDATA = try JSONDecoder().decode(Peticion.self, from: data)
//     print(data)
    } catch let jsonErr {
        print("cant decode", jsonErr)
    }

这是一个有趣的练习。这也是未经测试的代码,但是我很确定它会起作用。

答案 1 :(得分:-3)

import Foundation

// MARK: - WelcomeElement
struct WelcomeElement: Codable {
    let datosConexion: DatosConexion?
    let estadoLanzamiento: EstadoLanzamiento?
    let usuario: [Usuario]?

    enum CodingKeys: String, CodingKey {
        case datosConexion = "datos_conexion"
        case estadoLanzamiento = "estado_lanzamiento"
        case usuario
    }
}

// MARK: - DatosConexion
struct DatosConexion: Codable {
    let conexion: String
}

// MARK: - EstadoLanzamiento
struct EstadoLanzamiento: Codable {
    let tiempoRestante: Int
    let etapaActual: String

    enum CodingKeys: String, CodingKey {
        case tiempoRestante = "tiempo_restante"
        case etapaActual = "etapa_actual"
    }
}

// MARK: - Usuario
struct Usuario: Codable {
    let id, nombre, email, password: String
    let imagen, puesto, departamento: String

    enum CodingKeys: String, CodingKey {
        case id = "Id"
        case nombre = "Nombre"
        case email = "Email"
        case password = "Password"
        case imagen = "Imagen"
        case puesto = "Puesto"
        case departamento = "Departamento"
    }
}

typealias Welcome = [WelcomeElement]