Search code examples
iosjsonswiftalamofire

How To Return Glassdoor API in JSON Format


I am having some difficulties return the Glassdoor API found here https://www.glassdoor.com/developer/companiesApiActions.htm

How Can I return the entire company in JSON format So that I can display the company information as well as the ceo information.

So far I can display the company Information but I cannot access the Ceo data and featureReview data.

This is how I am making the Request but does not return the result entirely in JSON.

Alamofire.request(glassdoorURL).responseJSON { (response) in
print("================")

//if let JSON = response.result.value as? [String:AnyObject] { 
//dictionary
    //print("JSON: \(JSON)")
    //let employers = JSON["response"]!["employers"]!! as [[String:AnyObject]]

if let JSON = response.result.value as? [String:Any] { //dictionary

if let resp = JSON["response"] as?[String:Any] {  //dictionary

let employers = resp["employers"] as?[[String:Any]] //array

    print("Employers: \(employers!)")

     self.companies = self.filterCompanies(companyArray: employers!)  
  //takes the company and puts it into an array to display to a table

     self.researchTableView.reloadData()
 }
//}
}
print("================")
}

This is my Data Model.

final class GlassdoorCompany: NSObject {

var name: String? 
var websiteURL: String?
var industry: String?
var logo: String?
var overallRating: String?
var ceo: Ceo?
var featuredReview: FeaturedReview?

init(fromJSON json: NSDictionary) {
    if let nameStr = json["name"] as? String {
        self.name = nameStr
    }
    if let websiteURLStr = json["website"] as? String {
        self.websiteURL = websiteURLStr
    }
    if let industryStr = json["industry"] as? String {
        self.industry = industryStr
    }
    if let logoStr = json["squareLogo"] as? String {
        self.logo = logoStr
    }
    if let overallRatingStr = json["overallRating"] as? String {
        self.overallRating = overallRatingStr
    }
    if let ceoStr = json["ceo"] as? Ceo {
        self.ceo = ceoStr
    }
    if let featuredReviewStr = json["featuredReview"] as? 
 FeaturedReview {
        self.featuredReview = featuredReviewStr
    }
}

final class Ceo: NSObject {

var name: String?
var image: ceoImage?
var approvalRating: Int?
var disapprovalRating: Int?
var totalRatings: Int?

init?(fromJSON json: NSDictionary){

    if let nameStr = json["name"] as? String {
        self.name = nameStr
    }

    if let imageStr = json["image"] as? ceoImage {
        self.image = imageStr
    }

    if let approvalRatingStr = json["pctApprove"] as? Int {
        self.approvalRating = approvalRatingStr
    }

    if let disapprovalRatingStr = json["pctDisapprove"] as? Int {
        self.disapprovalRating = disapprovalRatingStr
    }

    if let totalRatingsStr = json["numberOfRatings"] as? Int {
        self.totalRatings = totalRatingsStr
    }
}

final class ceoImage: NSObject {

var height: Int?
var src: String?
var width: Int?

init?(fromJSON json: NSDictionary) {

    if let heightStr = json["height"] as? Int {
        self.height = heightStr
    }

    if let srcStr = json["src"] as? String {
        self.src = srcStr
    }

    if let widthStr = json["width"] as? Int {
        self.width = widthStr
    }
}

final class FeaturedReview {
var currentJob: Bool?
var reviewDate: String?
var jobTitle: String?
var location: String?
var headline: String?
var pros: String?
var cons: String?
var overallRating: Int?

init?(fromJSON json: NSDictionary) {

    if let currentJobStr = json["currentJob"] as? Bool {
        self.currentJob = currentJobStr
    }

    if let reviewDateStr = json["reviewDateTime"] as? String {
        self.reviewDate = reviewDateStr
    }

    if let jobTitleStr = json["jobTitle"] as? String {
        self.jobTitle = jobTitleStr
    }

    if let locationStr = json["location"] as? String {
        self.location = locationStr
    }

    if let headlineStr = json["headline"] as? String {
        self.headline = headlineStr
    }

    if let prosStr = json["pros"] as? String {
        self.pros = prosStr
    }

    if let consStr = json["cons"] as? String {
        self.cons = consStr
    }

    if let overallRatingStr = json["overall"] as? Int {
        self.overallRating = overallRatingStr
    }
}

Solution

  • The problem you have is that it is not possible to directly cast json objects straight to a swift class. So json["ceo"] as? Ceo and json["featuredReview"] as? FeaturedReview are just returning nil. So you need to change the way you have your class initialised.

    I have rewritten your Ceo and CeoImage classes to work, you'll just need to fix the FeaturedReview based on this. I have also added a Swift 4 Codable example which I recommend you should learn to use, since it is now becoming very popular and is a lot simpler.

    After implementing the new Ceo model below, change

    if let ceoStr = json["ceo"] as? Ceo {
        self.ceo = ceoStr
    }
    

    to

    if let ceoStr = Ceo(json["ceo"] as? Dictionary<String,Any>) {
        self.ceo = ceoStr
    }
    

    What you need to fix

    struct Ceo {
    
        let name: String
        let image: CeoImage
        let approvalRating: Int
        let disapprovalRating: Int
        let totalRatings: Int
    
        init?(_ dict: Dictionary<String,Any>?){
    
            guard
                let name = dict["name"] as? String,
                let image = CeoImage(dict["image"] as? Dictionary<String,Any>),
                let approvalRating = dict["pctApprove"] as? Int,
                let disapprovalRating = dict["pctDisapprove"] as? Int,
                let totalRatings = dict["numberOfRatings"] as? Int
            else {
                return nil
            }
            self.name = name
            self.image = image
            self.approvalRating = approvalRating
            self.disapprovalRating = disapprovalRating
            self.totalRatings = totalRatings
        }
    }
    
    struct CeoImage {
    
        let height: Int
        let src: String
        let width: Int
    
        init?(_ dict: Dictionary<String,Any>?) {
            guard
                let height = dict?["height"] as? Int,
                let src = dict?["src"] as? String,
                let width = dict?["width"] as? Int
            else {
                return nil
            }
            self.height = height
            self.src = src
            self.width = width
        }
    }
    

    Swift 4 Codable Example

    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            Alamofire.request(glassdoorURL).responseJSON { (response) in
    
                // We need to extract the `response` data from the json and convert
                // it back to `Data` for the JSONDecoder
                guard
                    let dict = response.result.value as? Dictionary<String,Any>,
                    let responseData = dict["response"] as? Dictionary<String,Any>,
                    let json = JSONSerialization.data(withJSONObject: responseData)
                else {
                    return
                }
    
                do {
                    let dateFormatter = DateFormatter()
                    dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SS"
    
                    let decoder = JSONDecoder()
                    decoder.dateDecodingStrategy = .formatted(dateFormatter)
                    let company = try decoder.decode(Company.self, from: json)
                    dump(company)
                } catch {
                    print("\n(error)\n")
                }
            }
        }
    }
    

    Model

    struct Company: Codable {
    
        let employers: Array<Employer>
    }
    
    struct Employer: Codable {
    
        let name: String
        let website: URL
        let industry: String
        let squareLogo: URL
        let overallRating: Int
        let ceo: CEO
        let featuredReview: FeaturedReview
    }
    
    struct CEO: Codable {
    
        struct CEOImage: Codable {
            let src: URL
            let height: Int
            let width: Int
        }
    
        let name: String
        let title: String
        let image: CEOImage
        let numberOfRatings: Int
        let pctApprove: Int
        let pctDisapprove: Int
    }
    
    struct FeaturedReview : Codable {
    
        let id: Int
        let currentJob: Bool
        let reviewDateTime: Date
        let jobTitle: String
        let location: String
        let headline: String
        let pros: String
        let cons: String
    }