Search code examples
iosswiftalamofirewebservice-clientswifty-json

Need SwiftyJSON model and api call with nested for loops for array with array of dictionaries


For eg: I need to extract all the values

Data: [
{
    "id": 1,
    "title": "some title",
    "details": "here are some details",
    "userId": 1,
    "hidden": false,
    "createdAt": "2018-02-14T07:02:33.000Z",
    "updatedAt": "2018-02-14T07:02:33.000Z",
    "contactId": 1,
    "noteimages": [
        {
            "id": 2,
            "imageUrl": "someimage222.jpg",
            "userId": 1,
            "hidden": false,
            "createdAt": "2018-02-14T07:02:58.000Z",
            "updatedAt": "2018-02-15T04:41:05.000Z",
            "noteId": 1
        },
  {
            "id": 2,
            "imageUrl": "someimage222.jpg",
            "userId": 1,
            "hidden": false,
            "createdAt": "2018-02-14T07:02:58.000Z",
            "updatedAt": "2018-02-15T04:41:05.000Z",
            "noteId": 1
        }
    ]
}
]

This is not working for me im getting the all the noteimages for single note instance

var notes = Note

var noteImages = NoteImage ....

Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in

    if response.result.error == nil {
        guard let data = response.data else { return }
        do {
            if let json = try JSON(data: data).array {
                print(json)
                for item in json {
                    let title = item["title"].stringValue
                    let details = item["details"].stringValue

                    //loop through nested array
                    for innerItem in item["noteimages"].arrayValue {
                        let noteImage = NoteImage(imageUrl: innerItem["imageUrl"].stringValue)
                        self.noteImages.append(noteImage)
                    }

                    print("note images: \(self.noteImages)")

                    let note = Note(title: title, details: details, noteImage: self.noteImages)
                    self.notes.append(note)
                }
                //print(response)
                completion(true)
            }
        } catch {
            debugPrint(error)
        }

    } else {
        completion(false)
        debugPrint(response.result.error as Any)
    }

}

Solution

  • You should create following Codable,

    typealias ResultResponse = [ResultResponseElement]
    
    struct ResultResponseElement: Codable {
        let id: Int
        let title, details: String
        let userID: Int
        let hidden: Bool
        let createdAt, updatedAt: String
        let contactID: Int
        let noteimages: [Noteimage]
    
        enum CodingKeys: String, CodingKey {
            case id, title, details
            case userID = "userId"
            case hidden, createdAt, updatedAt
            case contactID = "contactId"
            case noteimages
        }
    }
    
    struct Noteimage: Codable {
        let id: Int
        let imageURL: String
        let userID: Int
        let hidden: Bool
        let createdAt, updatedAt: String
        let noteID: Int
    
        enum CodingKeys: String, CodingKey {
            case id
            case imageURL = "imageUrl"
            case userID = "userId"
            case hidden, createdAt, updatedAt
            case noteID = "noteId"
        }
    }
    

    Let's say you have following json file, you can to parse it like this,

    let result = try JSONDecoder().decode(ResultResponse.self, from: data) //data is your json data
    

    FYI. app.quicktype.io is the nicest way to create Codable structs.