-1

First of all I'm really beginner in Swift. I'm stuck for hours on this.

Here is the problem, I'm using AlamoFire in order to make my request

func getListFiles(userId: String, page: Int)
{
    let parameters: Parameters = [
        "userId": userId,
        "page": page
    ]

    Alamofire.request(baseUrl + Endpoints.GET_RECORDS.rawValue, method: HTTPMethod.post, parameters: parameters)
        .responseData { response in
            if let result = response.result.value{
                do {
                    let data = try JSONDecoder().decode(ListFilesStruct.self, from: result)
                } catch {
                    print("\(error)")
                }
            }
    }
}

and I want to store data response in my structure "ListFilesStruct". But it enters in the "catch" and fails

Printing description of error:
▿ DecodingError
  ▿ typeMismatch : 2 elements
- .0 : Swift.Dictionary<Swift.String, Any>
▿ .1 : Context
  ▿ codingPath : 3 elements
    - 0 : CodingKeys(stringValue: "data", intValue: nil)
    ▿ 1 : _JSONKey(stringValue: "Index 6", intValue: 6)
      - stringValue : "Index 6"
      ▿ intValue : Optional<Int>
        - some : 6
    - 2 : CodingKeys(stringValue: "expert", intValue: nil)
  - debugDescription : "Expected to decode Dictionary<String, Any> but found a string/data instead."
  - underlyingError : nil

Here is the main structure, I want an array of FileDetail

struct ListFilesStruct: Codable
{
    var success: Bool?
    var data: [FileDetail]?
}

struct FileDetail: Codable
{
    var id: String?
    var expert: FileElement?
}

And it exactly fails because of FileElement structure , I don't know why

struct FileElement: Codable
{
    var id: String?
    var role_id: String?
    var avatar: String?
    var nom: String?
    var prenom: String?  
}

I really want to store Webservice data like that , thanks

EDIT : Expected JSON :

{
"success": true,
"data": [
    {
        "id": "A19007994",
        "expert": {
            "id": "74EJEEZM",
            "role_id": "EXPERT",
            "avatar": null,
            "nom": "METRTALZ",
            "prenom": "JEREMIE",
        }
     }
 ]
 }
Manu13k
  • 326
  • 1
  • 6
  • 20

1 Answers1

2

Use below struct for your expected json

class MyCustomJSON: Codable {
    let success: Bool
    let data: [Datum]

    enum CodingKeys: String, CodingKey {
        case success = "success"
        case data = "data"
    }

    init(success: Bool, data: [Datum]) {
        self.success = success
        self.data = data
    }
}

class Datum: Codable {
    let id: String
    let expert: Expert

    enum CodingKeys: String, CodingKey {
        case id = "id"
        case expert = "expert"
    }

    init(id: String, expert: Expert) {
        self.id = id
        self.expert = expert
    }
}

class Expert: Codable {
    let id: String
    let roleID: String
    let nom: String
    let prenom: String

    enum CodingKeys: String, CodingKey {
        case id = "id"
        case roleID = "role_id"
        case nom = "nom"
        case prenom = "prenom"
    }

    init(id: String, roleID: String, nom: String, prenom: String) {
        self.id = id
        self.roleID = roleID
        self.nom = nom
        self.prenom = prenom
    }
}

// MARK: Encode/decode helpers

class JSONNull: Codable, Hashable {

    public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
        return true
    }

    public var hashValue: Int {
        return 0
    }

    public init() {}

    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if !container.decodeNil() {
            throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encodeNil()
    }
}

and initialize like this

do {
     let myCustomJSON = try JSONDecoder().decode(MyCustomJSON.self, from: jsonData)
} catch {
  print("\(error)")
}

I tried my code in playground and everything works. enter image description here

Emre Önder
  • 2,408
  • 2
  • 23
  • 73