Search code examples
jsonswiftcodabledecodable

Swift : Codable Struct Always Nil


I Have the following JSON Response

{
    "status_code": 1000,
    "data": {
        "user_id": 1000,
        "bid": "E5PPD5E3",
        "province": 0,
        "location": "123,123"
    },
    "message": "Verified"
}

And This is my Struct

struct Basicresponse : Codable{

    var statusCode : Int!
    var message : String?
    var data : data?

    enum CodingKeys: String, CodingKey {

        case statusCode = "status_code"

    }

}

struct data : Codable{

      var province : Int
      var userID : Int
      var location : String
      var bid : String

      enum CodingKeys: String, CodingKey {

            case province, location , bid
            case userID = "user_id"

          }
  }

And

 do {


  let jsonData = try JSONDecoder().decode(Basicresponse.self, from: data!)

         if(jsonData.statusCode == 1000){

                print(jsonData)
         }else{
                 self.alert.show(target: self.view, message: jsonData.message!)
          }


            }
 catch let jsonerr {
          print("error serrializing error",jsonerr)
 }

But the result as below,

Basicresponse(statusCode: Optional(2000), message: nil, data: nil)

I don't know why both the data and the message are always nil ?! I tried the end point with Post man and its works fine but in my app its always nil, Am i missing something here ?

Any help will be much appreciated


Solution

  • The issue is that you’ve excluded message and data from your CodingKeys. But you can add them like so:

    struct Basicresponse: Codable {
        var statusCode : Int!
        var message : String?
        var data : data?
    
        enum CodingKeys: String, CodingKey {
            case statusCode = "status_code"
            case message, data
        }
    }
    

    The other alternative is to not supply CodingKeys at all and tell your decoder to do the snake case conversion for you.

    let data = """
    {
        "status_code": 1000,
        "data": {
            "user_id": 1000,
            "bid": "E5PPD5E3",
            "province": 0,
            "location": "123,123"
        },
        "message": "Verified"
    }
    """.data(using: .utf8)!
    
    struct BasicResponse: Codable {
        var statusCode: Int
        var message: String?
        var data: Bid?
    }
    
    struct Bid: Codable {
        var province: Int
        var userId: Int
        var location: String
        var bid: String
    }
    
    do {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let jsonData = try decoder.decode(BasicResponse.self, from: data)
    
        if jsonData.statusCode == 1000 {
            print(jsonData)
        } else {
            print(jsonData.message ?? "No message")
        }
    } catch let jsonError {
        print("error serializing error", jsonError)
    }
    

    I hope you don’t mind, but I’ve renamed your data type to be Bid (as data doesn’t conform to standard class naming conventions of starting with upper case letter and it’s too easily confused with the existing Data type). I don’t know if Bid is the right name, so use whatever you think is appropriate, but hopefully it illustrates the idea.