0

I have the following problem I need to retrieve an array of URL's from a JSON Object in order to download all the pictures of the products from an e-commerce site in my app.

The JSON I get looks like this:

  [
{
........
........
.........
........
"images": [
  {
    "id": 976,
    "date_created": "2016-08-10T15:16:49",
    "date_modified": "2016-08-10T15:16:49",
    "src": "https://i2.wp.com/pixan.wpengine.com/wp-content/uploads/2016/07/canasta-familia.jpg?fit=600%2C600&ssl=1",
    "name": "canasta-familia",
    "alt": "",
    "position": 0
  }
], 
.......
.......
.......

So far I've been able to get only one string from the array doing this.

Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers)
        .responseJSON { response in
 if let jsonValue = response.result.value {
                let jsonObject = JSON(jsonValue)
                var jsonArray = jsonObject[0]["images"][0]["src"].stringValue
                print(jsonArray)
    }
}

which gives me this

https://xx.xx.xx/xxxx.xxxxx.xxxx/xx-xxxxx/uploads/2016/07/canasta-familia.jpg?fit=600%2C600&ssl=1

But what I need is to access all the elements inside "images" & "src" not just the first element of the index of both.

How can I do this?

Any ideas?

Octavio Rojas
  • 187
  • 13

2 Answers2

3

Step 1:

Create a custom object to represent the pictures. We'll call this "Picture".

struct Picture {

    let id:Int
    let date_created:String
    let date_modified:String
    let src:String
    let name:String
    let alt:String
    let position:Int
}

Step 2:

Create an array to hold all of your product pictures. Make sure you pay attention to the scope in which you create it. It should ideally outside of your download function.

var productPictures = [Picture]()

Step 3:

Download your JSON file, make a Picture struct for each image, and add each Picture to your productPictures array.

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

            switch response.result {
            case .success:

                self.productPictures.removeAll()

                guard let json = response.result.value as? [String:Any] else {
                    print("couldn't retrieve json as a dictionary")
                    return
                }

                guard let images = json["images"] as? [AnyObject] else {
                    print("there was a problem accessing the images key")
                    return
                }

                for image in images {

                    guard let id = image["id"] as? Int,
                          let date_created = image["date_created"] as? String,
                          let date_modified = image["date_modified"] as? String,
                          let src = image["src"] as? String,
                          let name = image["name"] as? String,
                          let alt = image["alt"] as? String,
                          let position = image["position"] as? Int
                    else {
                        print("There was a problem accessing one of the picture variables, or it was missing")
                        continue
                    }

                    let newPicture = Picture(id: id,
                                             date_created: date_created,
                                             date_modified: date_modified,
                                             src: src,
                                             name: name,
                                             alt: alt,
                                             position: position)

                    self.productPictures.append(newPicture)
                }
            case .failure(let error):
                print("could not download and retrieve product images. An error occurred: \(error)")
                return
            }
    }

Now you have an array full of Picture structs, each containing all of the necessary information pulled from your JSON download.

Note

This doesn't use SwiftyJSON, but it should work and give you the same intended result. I hope this helps!

user3353890
  • 1,844
  • 1
  • 16
  • 31
  • This looks like an awesome solution I'll try it tomorrow thank you so much! – Octavio Rojas Nov 30 '16 at 04:27
  • You're welcome! I hope it helps. – user3353890 Nov 30 '16 at 06:17
  • for some reason I'm getting this error message. ("couldn't retrieve json as a dictionary") – Octavio Rojas Dec 01 '16 at 00:02
  • Hmm, that's weird. Is your json structured as a dictionary? Perhaps it's an array with a dictionary inside it? Those are easy fixes – user3353890 Dec 01 '16 at 20:08
  • it's an array of dictionaries, I tried @el tomato 's method and it worked but it'd be good to know what to do in a case like that. – Octavio Rojas Dec 01 '16 at 20:10
  • Ok, well i'm glad you got it working!....In a case like that, you would just change the casting call from as? [String:Any] to something like as? [[String:Any]]. That's basically saying "this object should be an array full of dictionaries, with each dictionary containing a String for the key and Any value type for the value. – user3353890 Dec 01 '16 at 20:15
1

The following lines of code should work as I've tested myself with an actual dataset.

import Alamofire
import SwiftyJSON

Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers)
    .responseJSON { response in
    if let jsonValue = response.result.value {
        let jsonObject = JSON(jsonValue)
        if let array = jsonObject.array {
            for i in 0..<array.count {
                if let images = array[i]["images"].array {
                    for i in 0..<images.count {
                        let src = images[i]["src"]
                        print(src) // save src in an array or whatever
                    }
                }
            }
        }       
    }
El Tomato
  • 6,479
  • 6
  • 46
  • 75