2

I try to call the POST Api with Alamofire but it's showing me an error of incorrect format.

This is my JSON response:

[
  {
    "_source": {
      "nome": "LOTERIAS BELEM",
      "endereco": "R DO COMERCIO, 279",
      "uf": "AL",
      "cidade": "BELEM",
      "bairro": "CENTRO"
    },
    "_id": "010177175"
  },
  {
    "_source": {
      "nome": "Bel Loterias"
    },
    "_id": "80224903"
  },
  {
    "_source": {
      "nome": "BELLEZA LOTERIAS",
      "endereco": "R RIVADAVIA CORREA, 498",
      "uf": "RS",
      "cidade": "SANTANA DO LIVRAMENTO",
      "bairro": "CENTRO"
    },
    "_id": "180124986"
  }
]

class Album: Codable {
    var _source :  [_source]

}

class _source: Codable {
    var nome :  String
    var endereco : String
    var uf : String
    var cidade : String
    var bairro : String
}

var arrList = [Album]()

And this is how i try to Decoding with Alamofire.

func request() {

        let urlString = URL(string: "My Url")
      //  Alamofire.request(url!).responseJSON {(response) in

        Alamofire.request(urlString!, method: .post, parameters: ["name": "belem"],encoding: JSONEncoding.default, headers: nil).responseJSON {
            (response) in

            switch (response.result) {
            case .success:
                if let data = response.data {
                    do {
                        let response = try JSONDecoder().decode([Album].self, from: data)
                        DispatchQueue.main.async {
                             self.arrList = response
                        }
                    }
                    catch {
                        print(error.localizedDescription)
                    }
                }
            case .failure( let error):
                print(error)
            }
       }
 }
staticVoidMan
  • 19,275
  • 6
  • 69
  • 98
Krunal Nagvadia
  • 1,083
  • 2
  • 12
  • 33
  • 8
    **Never ever** print `error.localizedDescription` when decoding JSON. Print `error`, it tells you exactly what's wrong. And stop using those ugly *objective-c-ish* underscore characters. Structs in Swift start with an uppercase letter! – vadian Mar 06 '19 at 19:23

2 Answers2

3

Just your Album model is incorrect.

struct Album: Codable {
    var source : Source
    var id     : String

    enum CodingKeys: String, CodingKey {
        case source = "_source"
        case id = "_id"
    }
}

struct Source: Codable {
    var nome     : String
    var endereco : String?
    var uf       : String?
    var cidade   : String?
    var bairro   : String?
}

If you don't want _id altogether then simply remove the related parts.
As for your Alamofire related code, that part is good.


Notable improvements:

  • Have avoided underscored variable name in model by customizing CodingKeys for key mapping purpose
  • Typenames should always start with a Capital letter (so _source is Source)
    • Similarly, variable names should always start with a lowercase letter
  • Made some variables optional (based on your updated response)
    • Keeping a variable non-optional means it must be present in the response for the model to be created
    • Making a variable optional means that key may or may not be present in the response and it not being there won't prevent the model from being created
staticVoidMan
  • 19,275
  • 6
  • 69
  • 98
  • Ok i try this but `keyNotFound(CodingKeys(stringValue: "_source", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"_source\", intValue: nil) (\"_source\").", underlyingError: nil))` Error is Showing – Krunal Nagvadia Mar 07 '19 at 16:24
  • @KrunalNagvadia Share your json response. Seems "_source" is missing for some object. Anyways, share what logs with `print(try? JSONSerialization.jsonObject(with: data, options: []))` in your alamofire request function – staticVoidMan Mar 07 '19 at 17:06
  • [https://drive.google.com/file/d/1V25FAlCQRYNKVAp695SFOzQlLFO8AsIA/view?usp=sharing] – Krunal Nagvadia Mar 07 '19 at 17:13
  • @KrunalNagvadia Hm... 7th object has only "nome" key and none of the rest. We'll have to make the rest optional in `Source` optional. – staticVoidMan Mar 07 '19 at 17:16
  • @KrunalNagvadia Check updated answer. Will add explanation in a short while. – staticVoidMan Mar 07 '19 at 17:17
  • what change you make please explain – Krunal Nagvadia Mar 07 '19 at 17:21
  • @KrunalNagvadia Check answer. The `Source` model has `String?` for all except `nome`. Meaning `nome` key will always be present in the response. – staticVoidMan Mar 07 '19 at 17:22
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189611/discussion-between-krunal-nagvadia-and-staticvoidman). – Krunal Nagvadia Mar 07 '19 at 18:17
  • @KrunalNagvadia I hope this answer has solved your problem. Kindly upvote/mark as accepted. – staticVoidMan Mar 08 '19 at 10:30
  • Thanks! you make me realize that all this time the problem was my model. :) – Pedro Trujillo Mar 08 '21 at 06:14
1

I would like to recommend you to use json4swift.com. You just have to copy your json and paste there. It will automatically create modal struct or class from your json.

Coming back to your question, Your class Album doesn't have array of [_source]. That's the reason you are getting following error "The data couldn’t be read because it isn’t in the correct format".

Try below given format of album class,

class Album: Codable
{ 
  var source: Source?
  var id: String?
}

Please try to avoid using underscore in Swift.

Yash Jadhav
  • 95
  • 1
  • 14