为了账号安全,请及时绑定邮箱和手机立即绑定

在SWIFT 3中正确解析JSON

在SWIFT 3中正确解析JSON

长风秋雁 2019-06-03 13:45:10
在SWIFT 3中正确解析JSON我试图获取一个JSON响应并将结果存储在一个变量中。在以前的SWIFT版本中,我已经有过这种代码的版本,直到GM版本的Xcode 8发布为止。我在StackOverflow上看了几篇类似的文章:SWIFT 2解析JSON-不能订阅‘AnyObject’类型的值和SWIFT 3中的JSON解析.然而,那里传达的想法似乎不适用于这种情况。如何在SWIFT 3中正确解析JSON响应?在SWIFT 3中读JSON的方式有什么变化吗?下面是所讨论的代码(可以在操场上运行):import Cocoalet url = "https://api.forecast.io/forecast/apiKey/37.5673776,122.048951"if let url = NSURL(string: url) {     if let data = try? Data(contentsOf: url as URL) {         do {             let parsedData = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments)         //Store response in NSDictionary for easy access        let dict = parsedData as? NSDictionary         let currentConditions = "\(dict!["currently"]!)"         //This produces an error, Type 'Any' has no subscript members                 let currentTemperatureF = ("\(dict!["currently"]!["temperature"]!!)" as NSString).doubleValue                     //Display all current conditions from API            print(currentConditions)             //Output the current temperature in Fahrenheit            print(currentTemperatureF)         }         //else throw an error detailing what went wrong        catch let error as NSError {             print("Details of JSON parsing error:\n \(error)")         }     }}编辑:下面是API调用的结果示例print(currentConditions)["icon": partly-cloudy-night, "precipProbability": 0, "pressure": 1015.39, "humidity": 0.75, "precipIntensity": 0, "windSpeed":  6.04, "summary": Partly Cloudy, "ozone": 321.13, "temperature": 49.45, "dewPoint": 41.75, "apparentTemperature": 47, "windBearing":  332, "cloudCover": 0.28, "time": 1480846460]
查看完整描述

4 回答

?
叮当猫咪

TA贡献1776条经验 获得超12个赞

对于SWIFT 3来说,Xcode 8 Beta 6发生了一个很大的变化,那就是id现在作为Any而不是AnyObject.

这意味着parsedData作为最有可能与类型一起返回的字典返回。[Any:Any]..如果不使用调试器,我就无法确切地告诉您的强制转换为什么。NSDictionary但你看到的错误是因为dict!["currently"]!有型Any

那你怎么解决这个问题?从你引用的方式来看,我想dict!["currently"]!是一本字典,所以你有很多选择:

首先,你可以这样做:

let currentConditionsDictionary: [String: AnyObject] = dict!["currently"]! as! [String: AnyObject]

这将为您提供一个字典对象,然后您可以查询它的值,这样您就可以得到如下所示的温度:

let currentTemperatureF = currentConditionsDictionary["temperature"] as! Double

或者如果你愿意的话,你可以排队:

let currentTemperatureF = (dict!["currently"]! as! [String: AnyObject])["temperature"]! as! Double

希望这会有所帮助,恐怕我还没有时间编写一个示例应用程序来测试它。

最后一个注意事项:最容易做的事情可能是简单地将JSON有效负载转换到[String: AnyObject]刚开始的时候。

let parsedData = try JSONSerialization.jsonObject(with: data as Data, options: .allowFragments) as! Dictionary<String, AnyObject>


查看完整回答
反对 回复 2019-06-03
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

let str = "{\"names\": [\"Bob\", \"Tim\", \"Tina\"]}"let data = str.data(using: String.Encoding.utf8, allowLossyConversion: false)!do {
    let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: AnyObject]
    if let names = json["names"] as? [String] {
        print(names)}} catch let error as NSError {
    print("Failed to load: \(error.localizedDescription)")}


查看完整回答
反对 回复 2019-06-03
?
繁花如伊

TA贡献2012条经验 获得超12个赞

我建的快速型正是为了这个目的。只需粘贴示例JSON,QuickType就会为您的API数据生成此类型层次结构:

struct Forecast {
    let hourly: Hourly
    let daily: Daily
    let currently: Currently
    let flags: Flags
    let longitude: Double
    let latitude: Double
    let offset: Int
    let timezone: String}struct Hourly {
    let icon: String
    let data: [Currently]
    let summary: String}struct Daily {
    let icon: String
    let data: [Datum]
    let summary: String}struct Datum {
    let precipIntensityMax: Double
    let apparentTemperatureMinTime: Int
    let apparentTemperatureLowTime: Int
    let apparentTemperatureHighTime: Int
    let apparentTemperatureHigh: Double
    let apparentTemperatureLow: Double
    let apparentTemperatureMaxTime: Int
    let apparentTemperatureMax: Double
    let apparentTemperatureMin: Double
    let icon: String
    let dewPoint: Double
    let cloudCover: Double
    let humidity: Double
    let ozone: Double
    let moonPhase: Double
    let precipIntensity: Double
    let temperatureHigh: Double
    let pressure: Double
    let precipProbability: Double
    let precipIntensityMaxTime: Int
    let precipType: String?
    let sunriseTime: Int
    let summary: String
    let sunsetTime: Int
    let temperatureMax: Double
    let time: Int
    let temperatureLow: Double
    let temperatureHighTime: Int
    let temperatureLowTime: Int
    let temperatureMin: Double
    let temperatureMaxTime: Int
    let temperatureMinTime: Int
    let uvIndexTime: Int
    let windGust: Double
    let uvIndex: Int
    let windBearing: Int
    let windGustTime: Int
    let windSpeed: Double}struct Currently {
    let precipProbability: Double
    let humidity: Double
    let cloudCover: Double
    let apparentTemperature: Double
    let dewPoint: Double
    let ozone: Double
    let icon: String
    let precipIntensity: Double
    let temperature: Double
    let pressure: Double
    let precipType: String?
    let summary: String
    let uvIndex: Int
    let windGust: Double
    let time: Int
    let windBearing: Int
    let windSpeed: Double}struct Flags {
    let sources: [String]
    let isdStations: [String]
    let units: String}

它还生成无依赖的封送处理代码,以诱骗JSONSerialization.jsonObject变成Forecast,包括一个使用JSON字符串的方便构造函数,这样您就可以快速解析强类型的Forecast评估和访问其字段:

let forecast = Forecast.from(json: jsonString)!print(forecast.daily.data[0].windGustTime)

可以从NPM安装QuickTypenpm i -g quicktype使用web用户界面将生成的完整代码粘贴到操场。


查看完整回答
反对 回复 2019-06-03
  • 4 回答
  • 0 关注
  • 767 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号