Keith
Keith

Reputation: 2009

SwiftyJson nested array with model

How do I create a data model with SwiftyJSON and a 2nd set of nested array of objects? I'm able to parse and store the top level objects fine, but not the inner ones. noteimages in particular, I can't seem to figure out. Below is the api results and under that is how I am trying to do it, although not quite right.

[
{
    "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
        }
    ]
}
]

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

                        var noteImages: [Dictionary<String, AnyObject>]
                        for image in item["noteimages"].arrayValue {
                            noteImages.append(image["imageUrl"])
                        }

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

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

    }

Upvotes: 2

Views: 1776

Answers (2)

Reinier Melian
Reinier Melian

Reputation: 20804

Your issue is that you are getting the value string in key imageUrl and you are adding as dictionary so if you need an array of dictionary you need to add those values in item["noteimages"].arrayValue directly or if you need an array of imageUrl you need to change the type of noteImages var to String type

var noteImages: [Dictionary<String, AnyObject>]// this should be [String:AnyObject]] swifty way
for image in item["noteimages"].arrayValue {
    noteImages.append(image["imageUrl"]) //this is an String not an Dictionary
}

To fix this you need one of three options

Option 1: Use an array of dictionary

var noteImages: [[String:AnyObject]] = []
for image in item["noteimages"].arrayValue {
   if let imageDict = image as? [String:AnyObject]{
       noteImages.append(imageDict) //adding in a dictionary array
    }
}

Option 2: Use an array of String

var noteImages: [String] = []
for image in item["noteimages"].arrayValue {
   if let imageDict = image as? [String:AnyObject]{
       noteImages.append(imageDict["imageUrl"])
    }
}

Option 3: convert your dictionary to a Model object

var noteImages: [YourModelName] = []
for image in item["noteimages"].arrayValue {
   if let imageDict = image as? [String:AnyObject]{
       noteImages.append(YourModelName(dictionary:imageDict)) //adding in a model object created from a dictionary
    }
}

Upvotes: 3

Keith
Keith

Reputation: 2009

This is what I ended up doing:

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)
        }

    }

Upvotes: 0

Related Questions