1

I have a JSON result from Alamofire and SwiftyJSON and am trying to create a dictionary from it to create an array

JSON Result

JSON: [
  {
    "p_589b6a49a0bfd" : {
      "path" : "\/uploads\/588fa43eba3c9\/588fa43eba3c9_1486580297.jpg",
      "likes" : "0",
      "userid" : "588fa43eba3c9",
      "caption" : "Bae",
      "comments" : "0",
      "date" : "1486580297"
    }
  },
  {
    "p_589b7f1c540f1" : {
      "path" : "\/uploads\/588fa43eba3c9\/588fa43eba3c9_1486585628.jpg",
      "likes" : "0",
      "userid" : "588fa43eba3c9",
      "caption" : "Hot stuff bitch ",
      "comments" : "0",
      "date" : "1486585628"
    }
  }
]

Request/Response

Alamofire.request(BASE_URL + "index.php/feed/build", method: .get, headers: headers).responseJSON { response in

        switch response.result {

        case .success(let value):
            let json = JSON(value)
            print("JSON: \(json)")

        case .failure(let error):
            print(error)

        }

    }

I have then set up a simple class called 'FeedPost' which will store each of the elements in JSON response (this is the function in the FeedPost class)

init(postid: String, postData: Dictionary<String, AnyObject>) {

    self._postid = postid

    if let caption = postData["caption"] as? String {
        self._caption = caption
    }

    if let path = postData["path"] as? String {
        self._path = path
    }

    if let likes = postData["likes"] as? Int {
        self._likes = likes
    }

    if let comments = postData["comments"] as? Int {
        self._comments = comments
    }

    if let userid = postData["userid"] as? String {
        self._userid = userid
    }

    if let date = postData["date"] as? String {
        self._date = date
    }

}

I need to somehow cycle through the JSON to create a dictionary to pass to FeedPost then add each FeedPost to another array called Posts during the request. The string that starts with 'p_' I want to use as the postid

2 Answers 2

3

With Alamofire response you have used SwiftyJSON and with your FeedPost init you are using swift native dictionary. So I'm suggesting you to either work with SwiftyJSON or with swift's native type. Since you have already added init with dictionary I'm answering your answer with native type.

  Alamofire.request(BASE_URL + "index.php/feed/build", method: .get, headers: headers).responseJSON { response in

    switch response.result {

    case .success(let value):
        If let dic = value as? [String: Any],
           let array = DIC["JSON"] as? [[String: Any]] {
               for item in array {
                    for (key, value) in item {
                          If let subDic = value as?  [String: Any] {
                                let obj =  FeedPost(postid: key, postData: subDic)
                          }
                    }
               }
        }
        print("JSON: \(json)")

    case .failure(let error):
        print(error)

    }

}

Note: Correct Dictionary notation for JSON in swift 3 is [String: Any] not [String: AnyObject] so change your init parameter postData's type to [String: Any].

Sign up to request clarification or add additional context in comments.

3 Comments

After the obj i append it to a variable var posts = [FeedPost]() self.posts.append(obj) But when i try to print it, it just prints [FeedPost, FeedPost]
@Chad You are printing array of FeedPost custom object so that it is showing you the object type, there is nothing wrong with it. Now you only need tableView to display information from this array.
@Chad Welcome mate :)
1

Below is the code which can be used for your case, This code is copied from playgrounds.

import UIKit

typealias JSONDictionary = [String: AnyObject]

    class Post {
        let id: String
        let userId: String?
        let date: Double?
        let caption: String?
        let comments: Double?
        let likes: Double?
        let path: String?

        init?(with dictionary: JSONDictionary) {
            guard let postId = dictionary.keys.first, let postInfo = dictionary[postId] as? JSONDictionary  else { return nil }

            self.id = postId
            self.userId = postInfo["userid"] as? String
            self.date = postInfo["date"] as? Double
            self.caption = postInfo["caption"] as? String
            self.comments = postInfo["comments"] as? Double
            self.likes = postInfo["likes"] as? Double
            self.path = postInfo["path"] as? String
        }
    }

Parsing JSON array will be like this.

case .success(let value):
    let jsonArray = value["JSON"] as? [JSONDictionary]
    let posts = jsonArray?.flatMap(Post.init(with:))
    print("Posts \(posts)"
case .failure: break

I have tried this using a local JSON file in a Playgrounds & code was something like this.

let url = Bundle.main.url(forResource: "data", withExtension: "json")
let data = try! Data(contentsOf: url!)

let jsonArray = try! JSONSerialization.jsonObject(with: data , options: .allowFragments) as? [JSONDictionary]
let posts = jsonArray?.flatMap(Post.init(with:))

4 Comments

With this code, i get 'Ambiguous reference to member jsonObject(with:options:) let jsonArray = try! JSONSerialization.jsonObject(with: value, options: .allowFragments) as? [JSONDictionary] let posts = jsonArray.flatMap(Post.init(with: JSONDictionary)) print("Posts \(posts)")
I think you don't need this code, you will get parsed json object i.e. value. I mentioned this in case if you are going to try this.
Ah I see so now using this let jsonArray = value["JSON"] as? [JSONDictionary] let posts = jsonArray?.flatMap(Post.init(with:)) i get type 'any' has no subscript members with the 'value' being highlighted as the error?
guard let value = value as? JSONDictionary else { fatalError("data is not quite right") }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.