Home > Mobile >  How would I print the title property in this returned JSON in Swift using URLSession and dataTask?
How would I print the title property in this returned JSON in Swift using URLSession and dataTask?

Time:06-27

I am working with an api and getting back some strangely formatted JSON.

[
    {
        "title": "Wales' new £2bn space strategy hopes",
        "url": "https://www.bbc.co.uk/news/uk-wales-60433763",
        "source": "bbc"
    },
    {
        "title": "Could Port Talbot become a centre of space tech? Video, 00:02:02Could Port Talbot become a centre of space tech?",
        "url": "https://www.bbc.co.uk/news/uk-wales-60471170",
        "source": "bbc"
    },
]

As you can see, there is no object name I can latch on to. I've tried making a model like this

struct SpaceNewsModel: Identifiable, Codable {
    var id = UUID()
    
    let title: String
    let url: String
    let source: String   
}

But once I get to using JSONDeocder() with the following code

                let decoder = JSONDecoder()
                if let safeData = data {
                    do {
                        let astroNews = try decoder.decode(SpaceNewsModel.self, from: safeData)
                        print(astroNews)
                        
                    } catch {
                        print("DEBUG: Error getting news articles \(error.localizedDescription)")
                    }
                }

I get the error DEBUG: Error getting news articles The data couldn’t be read because it isn’t in the correct format.

So how would you go about printing out each title, url, or source to the console? I've worked with JSON before and they are usually formatted differently.

CodePudding user response:

I found a workaround for this. Removing the identifiable protocol lets me access the data. Like so

struct SpaceNewsModel: Codable {

    let title: String
    let url: String
    let source: String
    
}

Then I can use decoder as normal

        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            if error != nil {
                print(error!)
            } else {
                
                let decoder = JSONDecoder()
                if let safeData = data {
                    do {
                        let astroNews = try decoder.decode([SpaceNewsModel].self, from: safeData)
                        
                        print(astroNews[0].title)

                        
                    } catch {
                        print("DEBUG: Error getting news articles \(error)")
                    }
                }

I did change let astroNews = try decoder.decode(SpaceNewsModel.self, from: safeData) to let astroNews = try decoder.decode([SpaceNewsModel].self, from: safeData)

Even with changing it to array type or not, as long as I had my SpaceNewsModel following the identifiable protocol, it would NOT work. It's a strange workaround, but it works for now.

CodePudding user response:

in addition to

 let astroNews = try decoder.decode([SpaceNewsModel].self, from: safeData)

use this for your SpaceNewsModel and

struct SpaceNewsModel: Identifiable, Codable {
    let id = UUID()  // <-- here, a let
    
    let title: String
    let url: String
    let source: String  

    enum CodingKeys: String, CodingKey { // <-- here 
         case title,url,source 
    }
 
}
  • Related