Search code examples
iosjsonswiftapialamofire

Swift 4 - Which type of array to use - Parse JSON response into Array


I'm working on Movie app for practice and I'm stuck on parsing JSON into Array. I'm using Alamofire for HTTP request and Unboxer for deserializing JSON into Object.

I'm getting JSON response in this form.

{
  "page": 1,
  "total_results": 19819,
  "total_pages": 991,
  "results": [
    {
      "vote_count": 6303,
      "id": 299536,
      "video": false,
      "vote_average": 8.4,
      "title": "Avengers: Infinity War",
      "popularity": 477.545,
      "poster_path": "/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg",
      "original_language": "en",
      "original_title": "Avengers: Infinity War",
      "genre_ids": [
        12,
        878,
        14,
        28
      ],
      "backdrop_path": "/bOGkgRGdhrBYJSLpXaxhXVstddV.jpg",
      "adult": false,
      "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.",
      "release_date": "2018-04-25"
    },
    {
      "vote_count": 485,
      "id": 353081,
      "video": false,
      "vote_average": 7.5,
      "title": "Mission: Impossible - Fallout",
      "popularity": 324.893,
      "poster_path": "/AkJQpZp9WoNdj7pLYSj1L0RcMMN.jpg",
      "original_language": "en",
      "original_title": "Mission: Impossible - Fallout",
      "genre_ids": [
        12,
        28,
        53
      ],
      "backdrop_path": "/5qxePyMYDisLe8rJiBYX8HKEyv2.jpg",
      "adult": false,
      "overview": "When an IMF mission ends badly, the world is faced with dire consequences. As Ethan Hunt takes it upon himself to fulfil his original briefing, the CIA begin to question his loyalty and his motives. The IMF team find themselves in a race against time, hunted by assassins while trying to prevent a global catastrophe.",
      "release_date": "2018-07-25"
    },
    {
      "vote_count": 2408,
      "id": 351286,
      "video": false,
      "vote_average": 6.6,
      "title": "Jurassic World: Fallen Kingdom",
      "popularity": 177.698,
      "poster_path": "/c9XxwwhPHdaImA2f1WEfEsbhaFB.jpg",
      "original_language": "en",
      "original_title": "Jurassic World: Fallen Kingdom",
      "genre_ids": [
        28,
        12,
        878
      ],
      "backdrop_path": "/3s9O5af2xWKWR5JzP2iJZpZeQQg.jpg",
      "adult": false,
      "overview": "Several years after the demise of Jurassic World, a volcanic eruption threatens the remaining dinosaurs on the island of Isla Nublar. Claire Dearing, the former park manager and founder of the Dinosaur Protection Group, recruits Owen Grady to help prevent the extinction of the dinosaurs once again.",
      "release_date": "2018-06-06"
    },
    {
      "vote_count": 1023,
      "id": 363088,
      "video": false,
      "vote_average": 7,
      "title": "Ant-Man and the Wasp",
      "popularity": 146.389,
      "poster_path": "/rv1AWImgx386ULjcf62VYaW8zSt.jpg",
      "original_language": "en",
      "original_title": "Ant-Man and the Wasp",
      "genre_ids": [
        28,
        12,
        14,
        35,
        878
      ],
      "backdrop_path": "/6P3c80EOm7BodndGBUAJHHsHKrp.jpg",
      "adult": false,
      "overview": "As Scott Lang awaits expiration of his term of house detention, Hope van Dyne and Dr. Hank Pym involve him in a scheme to rescue Mrs. van Dyne from the micro-universe into which she has fallen, while two groups of schemers converge on them with intentions of stealing Dr. Pym's inventions.",
      "release_date": "2018-07-04"
    },
    {
      "vote_count": 3693,
      "id": 954,
      "video": false,
      "vote_average": 6.8,
      "title": "Mission: Impossible",
      "popularity": 135.99,
      "poster_path": "/vmj2PzTLC6xJvshpq8SlaYE3gbd.jpg",
      "original_language": "en",
      "original_title": "Mission: Impossible",
      "genre_ids": [
        12,
        28,
        53
      ],
      "backdrop_path": "/tjQHn6xW5BiB1RJ3OZIPDzIOSkF.jpg",
      "adult": false,
      "overview": "When Ethan Hunt, the leader of a crack espionage team whose perilous operation has gone awry with no explanation, discovers that a mole has penetrated the CIA, he's surprised to learn that he's the No. 1 suspect. To clear his name, Hunt now must ferret out the real double agent and, in the process, even the score.",
      "release_date": "1996-05-22"
    },
    {
      "vote_count": 3376,
      "id": 383498,
      "video": false,
      "vote_average": 7.6,
      "title": "Deadpool 2",
      "popularity": 122.498,
      "poster_path": "/to0spRl1CMDvyUbOnbb4fTk3VAd.jpg",
      "original_language": "en",
      "original_title": "Deadpool 2",
      "genre_ids": [
        28,
        35,
        878
      ],
      "backdrop_path": "/3P52oz9HPQWxcwHOwxtyrVV1LKi.jpg",
      "adult": false,
      "overview": "Wisecracking mercenary Deadpool battles the evil and powerful Cable and other bad guys to save a boy's life.",
      "release_date": "2018-05-15"
    },
    {
      "vote_count": 1550,
      "id": 260513,
      "video": false,
      "vote_average": 7.7,
      "title": "Incredibles 2",
      "popularity": 121.637,
      "poster_path": "/x1txcDXkcM65gl7w20PwYSxAYah.jpg",
      "original_language": "en",
      "original_title": "Incredibles 2",
      "genre_ids": [
        28,
        12,
        16,
        10751
      ],
      "backdrop_path": "/mabuNsGJgRuCTuGqjFkWe1xdu19.jpg",
      "adult": false,
      "overview": "Elastigirl springs into action to save the day, while Mr. Incredible faces his greatest challenge yet – taking care of the problems of his three children.",
      "release_date": "2018-06-14"
    },
    {
      "vote_count": 4240,
      "id": 177677,
      "video": false,
      "vote_average": 7.1,
      "title": "Mission: Impossible - Rogue Nation",
      "popularity": 112.192,
      "poster_path": "/z2sJd1OvAGZLxgjBdSnQoLCfn3M.jpg",
      "original_language": "en",
      "original_title": "Mission: Impossible - Rogue Nation",
      "genre_ids": [
        28,
        12,
        53
      ],
      "backdrop_path": "/8XeLfNQrDmFQmPTqxapfWUnKiLf.jpg",
      "adult": false,
      "overview": "Ethan and team take on their most impossible mission yet, eradicating the Syndicate - an International rogue organization as highly skilled as they are, committed to destroying the IMF.",
      "release_date": "2015-07-23"
    },
    {
      "vote_count": 3350,
      "id": 333339,
      "video": false,
      "vote_average": 7.7,
      "title": "Ready Player One",
      "popularity": 109.135,
      "poster_path": "/pU1ULUq8D3iRxl1fdX2lZIzdHuI.jpg",
      "original_language": "en",
      "original_title": "Ready Player One",
      "genre_ids": [
        12,
        878,
        14
      ],
      "backdrop_path": "/5a7lMDn3nAj2ByO0X1fg6BhUphR.jpg",
      "adult": false,
      "overview": "When the creator of a popular video game system dies, a virtual contest is created to compete for his fortune.",
      "release_date": "2018-03-28"
    },
    {
      "vote_count": 5022,
      "id": 56292,
      "video": false,
      "vote_average": 6.9,
      "title": "Mission: Impossible - Ghost Protocol",
      "popularity": 99.389,
      "poster_path": "/s58mMsgIVOFfoXPtwPWJ3hDYpXf.jpg",
      "original_language": "en",
      "original_title": "Mission: Impossible - Ghost Protocol",
      "genre_ids": [
        28,
        53,
        12
      ],
      "backdrop_path": "/pc7a2qrIkIxzqWGqcexd3mHzIxy.jpg",
      "adult": false,
      "overview": "Ethan Hunt and his team are racing against time to track down a dangerous terrorist named Hendricks, who has gained access to Russian nuclear launch codes and is planning a strike on the United States. An attempt to stop him ends in an explosion causing severe destruction to the Kremlin and the IMF to be implicated in the bombing, forcing the President to disavow them. No longer being aided by the government, Ethan and his team chase Hendricks around the globe, although they might still be too late to stop a disaster.",
      "release_date": "2011-12-07"
    }
  ]
 }

Everything is working fine, i'm getting JSON response in String type over Alamofire request but the problem starts when i need to parse JSON response into array type.

public class APIManager : NSObject {

    static public func GetPopularMovies(){ // Get all POSTS
        Alamofire.request(APIRouter.GetPopularMovies()).responseJSON { response in
            if let json = response.result.value as? Array<Dictionary<String, Any >>
            {
                var movies : [Movie]
                movies = try! unbox(dictionaries: json)


                print("GetPopularMovies() -> Executed")
                print("JSON: \(json)") // JSON Response

            } else {
                print(response.result.value!)
            }
        }
    }        
}

The if statemant is always false, and i don't know in which type of array should I parse JSON response.

Here are the models i'm using to deserialize JSON with Unboxer.

struct Movie {
    let id : Int
    let original_title : String
    let overview : String
}

extension Movie : Unboxable {
    init(unboxer : Unboxer) throws {
        self.id = try unboxer.unbox(key: "id")
        self.original_title = try unboxer.unbox(key: "original_title")
        self.overview = try unboxer.unbox(key: "overview")
    }

}

struct Genre {
    let id : Int
    let name : String
}

extension Genre : Unboxable {
    init(unboxer : Unboxer) throws {
        self.id = try unboxer.unbox(key: "id")
        self.name = try unboxer.unbox(key: "name")
    }
}

It would be great if you could help me with resolving this problem, I've never had problem like this before because probably i was using API's with smaller and easier responses.

Thank you guys very much!


Solution

  • I think you are using array of dictionary for your response in this line -

     Array<Dictionary<String, Any >>
    

    But your json response is a dictionary which contains the array of results. If you want the parse the results array then you must parse only the results not the conplete response like this -

    if let json = response.result.value as? [String: Any]
            {
    let results = json["results"] as? [[String: Any]]
     let movies : [Movie] = try! unbox(dictionaries: results)
    
     print("GetPopularMovies() -> Executed")
     print("JSON: \(json)") // JSON Response
    
            } else {
                print(response.result.value!)
            }