skip to Main Content

I am very new to Swift, so please pardon me if it is a silly question
How to handle this type of response into data model ,response is in this form:

{
    "id" = 1;
    count = "";
    data = "[{"key":"value","key":"value".......}]";
    message = SUCCESS;
    "response_code" = 1;
}

The AlamofireRequest gets the response and prints it but when using responseDecodable,nothing happens, the code of Alamofire request is below:

let request = AF.request(urlString!,method: .get)
        
request.responseJSON { (data) in
  print(data)
}
        
request.responseDecodable(of: Test.self) { (response) in 
    guard let getData = response.value else {return}
    print(getData.all[0].firstName)  //Nothing prints
}

And this is how the data model looks like:

struct Test: Decodable {
   
    let firstName: String

    enum CodingKeys: String, CodingKey {
        case firstName = "first_name" 
        //firstname is inside data of json
    }
}

struct Getdata: Decodable {
    let all : [Test]
    
    enum CodingKeys: String, CodingKey {
        case all = "data"
    }
}

Want to access values inside data and print it. Please shed some light on it!

2

Answers


  1. Chosen as BEST ANSWER

    Did lot of silly mistakes in original question, long way to go

    As suggested by @flanker I did respecify the data model to

    struct Test : Codable {
        let id : String?
        let message : String?
        let data : String?
        let count : String?
        let response_code : String?
    
        enum CodingKeys: String, CodingKey {
    
            case id = "$id"
            case message = "message"
            case data = "data"
            case count = "count"
            case response_code = "response_code"
        }
           init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            id = try values.decodeIfPresent(String.self, forKey: .id)
            message = try values.decodeIfPresent(String.self, forKey:  .message)
            data = try values.decodeIfPresent(String.self, forKey: .data)
            count = try values.decodeIfPresent(String.self, forKey: .count)
            response_code = try values.decodeIfPresent(String.self, forKey: .response_code)
        }
    
    

    And now it seems to work

    Now getting the desired output [["key1": "value1", "key2": "value2"]]


  2. Trying to address both the question and the comments above, the first thing would be to get some valid JSON. It could be that your API is providing non-JSON data, in which case neither this answer or using AlamoFire to decode it will work. However, formatting the above as JSON, at my best guess of what it’s meant to be, will give:

    let json = """
    {
      "id": 1,
      "count": "",
      "data": [
        {
          "key1": "value1",
          "key2": "value2"
        }
      ],
      "message": "SUCCESS",
      "response_code": 1
    }
    """
    

    At this point it’s more obvious that the content under the data key is not an array of Test as defined above, but is an array of dictionaries (with a single enry in the array in the example). So it will be necessary to respecify the data model. For something this simple, for the use case mentioned, there is no real reason to go for multiple types, so we’re going to redefine Getdata (I’m sticking with your naming despite not liking it):

    struct Getdata: Decodable {
       let all : [[String:String]]
       
       enum CodingKeys: String, CodingKey {
          case all = "data"
       }
    }
    

    To test the decoding let’s used the standard JSONDecoder (I don’t have a Playground handy with AlamoFire as I’d never use it):

    
    do {
       let wrapper = try JSONDecoder().decode(Getdata.self, from: Data(json.utf8))
       print(wrapper.all)
    } catch {
       print("Decoding error (error.localizedDescription)")
    }
    

    This outputs

    [["key1": "value1", "key2": "value2"]]

    as would be expected.

    Now there’s a valid JSON decoding solution it should be easy to drop this into the AlamoFire APIs if you so wish. Although if the backend really is providing the misformed JSON as in question this won’t work and you’ll have to change the backend, decode it with your own decoder or mangle it into valid JSON.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search