无法将类型[[String:任何]]的值转换为预期的参数类型'数据'Alamofire-可编码

时间:2019-08-26 02:36:19

标签: swift xcode10.1

我是编程新手,所以很抱歉,如果此修复程序很简单。我正在尝试从Alamofire请求中获取JSON数据,以使其在控制台中不显示为可选内容。

我已经尝试过response.data,它确实将数据作为可选项提供给我,但我不知道如何在此调用中解开该可选项。我已经搜索并看到了result.value可能更接近我的需求。以下是到目前为止的内容。这将导致“无法将类型[[String:Any]”的值转换为预期的参数类型“数据””错误。

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)
            }


                     }
                }

我的最终目标是将JSON数据打印到表格视图中,包括图像和日期。我认为能够解开此可选内容是确定下一部分的第一步。

2 个答案:

答案 0 :(得分:0)

如果要访问从请求返回的原始Data,则需要使用responseDataresponseJSON使用JSONSerialization解析响应,并为您提供一个Any的值。 responseData为您提供了返回的原始Data,因此您可以像目前一样解开包装,并使用JSONDecoder

您还可以更新到Alamofire 5(当前为Beta),并使用responseDecodable来自动解析Decodable类型。

答案 1 :(得分:0)

  

我已经尝试过response.data,它确实将数据作为可选项提供给我,但我不知道如何在此调用中解开该可选项。

您绝对应该学习如何正确包装可选件。基本上,归结为当值为nil时要执行的操作。如果无法以某种方式无法获取数据,没有互联网,服务器没有响应或任何可能的原因,response.data可能是nil

考虑在这种情况下要发生的事情。您是否要显示错误以提醒用户?您要重试还是什么都不做?

然后使用此代码:

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)
}