Search code examples
jsonswiftdictionaryswift4alamofire

Parse dictionary behaviour strange


Parse dictionary value if one key value is null and other is key not null.

Value from source the name key unable to parse if the value of id is null. If the value of id not null then its returns the name value.

    {
    "status": "ok",
    "totalResults": 70,
    "articles": [
        {
            "source": {
                "id": null,
                "name": "Bloombergquint.com"
            },
            "author": "Aman Kapadia, Forum Bhatt",
            "title": "Infibeam Auditors Raise Questions On Loans To Vendors - BloombergQuint",
            "description": "Auditors to Infibeam Avenues raise questions about loans to vendors.",
            "url": "https://www.bloombergquint.com/business/infibeam-auditors-raise-questions-on-loans-to-vendors",
            "urlToImage": "https://images.assettype.com/bloombergquint%2F2018-02%2F11136839-3c0c-4356-b4d3-c918f4d417ad%2F323233043_1-9%20(1).jpg?rect=0%2C204%2C4000%2C2100&w=1200&auto=format%2Ccompress",
            "publishedAt": "2019-02-15T14:58:37Z",
            "content": "Auditors to Infibeam Avenues Ltd. raised questions about loans to vendors and how it recognises revenue in a fresh concern for the online retailer. SRBC & Co. LLP, the audit arm of EY, and Shah & Taparia sought more information to justify the rational… [+1985 chars]"
        },
        {
            "source": {
                "id": null,
                "name": "Moneycontrol.com"
            },
            "author": null,
            "title": "RBI lifts cap on FPI investments in corporate bonds - Moneycontrol.com",
            "description": "While the provision was aimed at incentivising FPIs to maintain a portfolio of assets, market feedback indicates that foreign portfolio investors (FPIs) have been constrained by this stipulation, the RBI said.",
            "url": "https://www.moneycontrol.com/news/business/rbi-lifts-cap-on-fpi-investments-in-corporate-bonds-3545571.html",
            "urlToImage": "https://static-news.moneycontrol.com/static-mcnews/2017/03/RBI-770x433.jpg",
            "publishedAt": "2019-02-15T13:26:00Z",
            "content": "The Reserve Bank of India (RBI) Friday withdrew the 20 per cent limit on investments by FPIs in corporate bonds of an entity with a view to encourage more foreign investments. As part of the review of the FPI investment in corporate debt undertaken in April 2… [+696 chars]"
        },
        {
            "source": {
                "id": null,
                "name": "Rushlane.com"
            },
            "author": "Rishabh Jain",
            "title": "2019 Honda Civic Review test drive - Still got the charm? - RushLane",
            "description": "Honda is back with the Civic in India. But does it have enough to attract those who love driving?",
            "url": "https://www.rushlane.com/2019-honda-civic-review-test-drive-12297473.html",
            "urlToImage": "https://www.rushlane.com/wp-content/uploads/2019/02/2019-honda-civic-review-test-drive-photos-specs-launch-price-14.jpg",
            "publishedAt": "2019-02-15T12:59:00Z",
            "content": "The Civic happens to be one of most loved brands from Honda in India. Globally too, it is one of those rare brands which have seen 10 proper generation changes. It is sold in multiple body types like Sedan, Coupe and Hatchback, however the Indian market only … [+8342 chars]"
        },
        {
            "source": {
                "id": null,
                "name": "Team-bhp.com"
            },
            "author": "Aditya Nadkarni",
            "title": "Maruti Swift, Dzire, Ertiga could get CNG variants - Team-BHP",
            "description": "According to a media report, Maruti Suzuki might introduce CNG variants of its cars in the years to come. The move could be taken in response to comply with the BS-VI emission norms, which are scheduled ...",
            "url": "https://www.team-bhp.com/news/maruti-swift-dzire-ertiga-could-get-cng-variants",
            "urlToImage": "https://www.team-bhp.com/sites/default/files/styles/large/public/1_639.jpg",
            "publishedAt": "2019-02-15T12:43:30Z",
            "content": "According to a media report, Maruti Suzuki might introduce CNG variants of its cars in the years to come. The move could be taken in response to comply with the BS-VI emission norms, which are scheduled to be implemented in 2020 and tighter fuel efficiency no… [+1119 chars]"
        }
   ]
}

ModelClass

private struct Headline: Decodable {
    let author: String
    let title: String
    let source: Source

    struct Source: Codable {
        var id : String
        var name : String
    }

    private enum CodingKeys: String, CodingKey {

        case author
        case title
        case source
    }
}

Inside ViewController

let url = ""
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .secondsSince1970
    // It is necessary for correct decoding. Timestamp -> Date.

        Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil)
            .responseJSON { response in
                switch response.result {
                case .success:
//                    ??? how to assing here! access the value global????
                case .failure(let error):
                    print("Request failed with error: \(error)")
            }
        }
    }

Inside cellForRowAt

cell.lbl_NewsTitle?.text = headlines[indexPath.row].title
cell.lbl_NewsSource?.text = headlines[indexPath.row].source["name"]

Its print only when id hold some String value else source.name return nil

Can any one advice why its like this? I am first time using swift language. :(


Solution

  • For Decodable you have to add the umbrella struct and you have to declare author in Headline and id in Source as optional because they can be null. All CodingKeys are synthesized.

    struct Response : Decodable {
        let status: String
        let totalResults: Int
        let articles: [Headline]
    }
    
    struct Headline: Decodable {
        let author: String?
        let title: String
        let source: Source
        let publishedAt : Date
    
        struct Source: Decodable {
            let id: String?
            let name: String
        }
    } 
    

    Rather than .secondsSince1970 the date decoding strategy must be .iso8601.

    This code assignes the articles array to the data source and reloads the table view on the main thread

    let url = ""
    
        Alamofire.request(url).responseJSON { response in
            switch response.result {
            case .success:
                let decoder = JSONDecoder()
                decoder.dateDecodingStrategy = .iso8601
                do {
                   let result = try decoder.decode(Response.self, from: response.data!)
                   self.headlines = result.articles
                   DispatchQueue.main.async {
                        self.tableView.reloadData()
                   }
                } catch { print("Decoding error:", error) }
            case .failure(let error):
                print("Request failed with error: \(error)")
            }
        }
    }
    

    The data source array must be declared as

    var headlines = [Headline]()
    

    In cellForRowAt write

    let headline = headlines[indexPath.row]
    cell.lbl_NewsTitle?.text = headline.title
    cell.lbl_NewsSource?.text = headline.source.name