swiftxcode10.1

Cannot convert value of type '[String : Any]' to expected argument type 'Data' Alamofire - Codable


I'm new to programming so apologies if the fix is a simple one. I'm trying to get the JSON data from the Alamofire request to show up not as an optional in the console.

I've already tried response.data which does give me the data as an optional but I don't know how to unwrap that optional in this call. I've searched and have seen that result.value might be closer to what I need. Below is what I have so far. This results in a "Cannot convert value of type '[String : Any]' to expected argument type 'Data'" error.

JSON File-->

"forecasts": [
        {
            "dateLabel": "今日",
            "telop": "晴時々曇",
            "date": "2019-08-16",
            "temperature": {
                "min": null,
                "max": null
            },
            "image": {
                "width": 50,
                "url": "http://weather.livedoor.com/img/icon/2.gif",
                "title": "晴時々曇",
                "height": 31
            }
        },
        {
            "dateLabel": "明日",
            "telop": "晴時々曇",
            "date": "2019-08-17",
            "temperature": {
                "min": {
                    "celsius": "27",
                    "fahrenheit": "80.6"
                },
                "max": {
                    "celsius": "37",
                    "fahrenheit": "98.6"
                }
            },
            "image": {
                "width": 50,
                "url": "http://weather.livedoor.com/img/icon/2.gif",
                "title": "晴時々曇",
                "height": 31
            }
        },
        {
            "dateLabel": "明後日",
            "telop": "晴時々曇",
            "date": "2019-08-18",
            "temperature": {
                "min": null,
                "max": null
            },
            "image": {
                "width": 50,
                "url": "http://weather.livedoor.com/img/icon/2.gif",
                "title": "晴時々曇",
                "height": 31
            }
        }
    ],
    "location": {
        "city": "東京",
        "area": "関東",
        "prefecture": "東京都"
    },
    "publicTime": "2019-08-16T17:00:00+0900",
    "copyright": {
        "provider": [
            {
                "link": "http://tenki.jp/",
                "name": "日本気象協会"
            }
        ],
        "link": "http://weather.livedoor.com/",
        "title": "(C) LINE Corporation",
        "image": {
            "width": 118,
            "link": "http://weather.livedoor.com/",
            "url": "http://weather.livedoor.com/img/cmn/livedoor.gif",
            "title": "livedoor 天気情報",
            "height": 26
        }
    }

Data model-->

import Foundation
import Alamofire

// MARK: - WeatherData
struct WeatherData: Codable {
    let forecasts: [Forecast]
}


struct Forecast: Codable {
    let dateLabel, telop, date: String
    let temperature: Temperature
    let image: Image

    enum CodingKeys: String, CodingKey {
        case dateLabel = "dateLabel"
        case telop = "telop"
        case date = "date"
        case temperature
        case image
    }
}


struct Image: Codable {
    let width: Int
    let url: String
    let title: String
    let height: Int

    enum CodingKeys: String, CodingKey {
        case width = "width"
        case url = "url"
        case title = "title"
        case height = "height"
    }
}


struct Temperature: Codable {
    let min, max: Max?


    enum CodingKeys: String, CodingKey {
        case min = "min"
        case max = "max"

    }

}


struct Max: Codable {
    let celsius, fahrenheit: String


    enum CodingKeys: String, CodingKey {
        case celsius = "celsius"
        case fahrenheit = "fahrenheit"

    }
}

viewcontroller-->

import UIKit
import Alamofire

class ForecastTableViewController: UITableViewController {

    let WEATHER_URL = "http://weather.livedoor.com/forecast/webservice/json/v1?city=130010"


    override func viewDidLoad() {
        super.viewDidLoad()

        Alamofire.request(WEATHER_URL).responseJSON { (response) in

                if let data = response.result.value as? [String: Any]{
                let decoder = JSONDecoder()
                let forecast = try? decoder.decode(WeatherData.self, from: data)
                print(forecast?.forecasts)
            }


                     }
                }

My ultimate goal is to print out the JSON data into a tableview, including the images and dates. I think being able to unwrap this optional is the first step before I figure out the next part.


Solution

  • I've already tried response.data which does give me the data as an optional but I don't know how to unwrap that optional in this call.

    You definitely should learn how to unwrap optionals properly. It basically comes down to what do you want to do when the value is nil. response.data could be nil when somehow the data could not be fetched, there's no internet, the server doesn't respond, or whatever reason it might be.

    Think about what you want to happen in such a situation. Do you want to show an error as an alert to the user? Do you want to try again, or just do nothing?

    And then use this code:

    Alamofire.request(WEATHER_URL).responseData { (response) in
    
        guard let data = response.data else {
            // do the stuff you want to do when the data failed to be fetched
            return
        }
        let decoder = JSONDecoder()
        guard let forecast = try? decoder.decode(WeatherData.self, from: data) else {
            // do the stuff you want to do when the data is not in the right format
            return
        }
        print(forecast?.forecasts)
    }