Как найти конкретную информацию, хранящуюся в формате данных json в API погоды

Я пишу проект Swift, чтобы получить данные о погоде из погодного API Wunderground. Теперь я могу извлекать такую ​​информацию, как температура или относительная влажность, но у меня возникают проблемы с получением информации, хранящейся во внутреннем списке вложенного списка, с помощью swift. Например, я не могу получить информацию о «display_location.state», хранящуюся в «current_observation».

Вот пример информации о погоде, предоставляемой Wunderground:

{
  "response": {
  "version":"0.1",
  "termsofService":"http://www.wunderground.com/weather/api/d/terms.html",
  "features": {
  "conditions": 1
  }
    }
  , "current_observation": {
        "image": {
        "url":"http://icons.wxug.com/graphics/wu2/logo_130x80.png",
        "title":"Weather Underground",
        "link":"http://www.wunderground.com"
        },
        "display_location": {
        "full":"San Francisco, CA",
        "city":"San Francisco",
        "state":"CA",
        "state_name":"California",
        "country":"US",
        "country_iso3166":"US",
        "zip":"94101",
        "magic":"1",
        "wmo":"99999",
        "latitude":"37.77500916",
        "longitude":"-122.41825867",
        "elevation":"47.00000000"
        },
        "temperature_string":"76.3 F (24.6 C)",
        "relative_humidity":"43%",
    }
}

Вот мой Swift-код для извлечения информации о погоде:

var url = NSURL(string:"http://api.wunderground.com/api/56968011acc3e3eb/conditions/q/\(state)/\(city).json")
var data = NSData.dataWithContentsOfURL(url, options: NSDataReadingOptions.DataReadingUncached, error: nil)
var str = NSString(data:data, encoding:NSUTF8StringEncoding)
var json:AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil)
var weatherInfo:AnyObject! = json.objectForKey("current_observation")
var currentTemp: AnyObject! = weatherInfo.objectForKey("temperature_string")
var humidity:AnyObject! = weatherInfo.objectForKey("relative_humidity")
var wind:AnyObject! = weatherInfo.objectForKey("wind_kph")
display.text = "Temperature: \(currentTemp)\nHumidity: \(humidity)\nWind: \(wind)\n"

Спасибо!


person Yahui    schedule 05.10.2014    source источник


Ответы (1)


Небольшое замечание по стилю: вы должны использовать let вместо var каждый раз, когда вы не собираетесь изменять значение вашей переменной после ее первой установки.

Единственное, что выглядит неправильно, - это то, как вы извлекаете подобъекты из JSON. Имейте в виду, что структуры данных в JSON выглядят следующим образом

NSDictionary {
    "response": NSDictionary {},
    "current_observation": NSDictionary {
          "relative_humidity": NSString
          ...
    }
    ...
}

Поэтому, когда вы вытаскиваете такие объекты, как current_observation, вам нужно убедиться, что вы применяете их к нужным объектам.

let json = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.AllowFragments, error:nil) as NSDictionary
let weatherInfo = json["current_observation"] as NSDictionary
let currentTemp = weatherInfo["temperature_string"] as NSString
...

Хотя, честно говоря, для чего-то вроде этого я бы рекомендовал использовать EasyMapping. Затем вы можете просто настроить быстрые классы для представления JSON и поставщика карты, чтобы вы могли просто сделать что-то вроде

if let weatherInfo = EKMapper.objectFromExternalRepresentation(json, withMapping:/*mapping provider*/) {
    //do stuff
}

а затем все это десериализовано из JSON в быстрые объекты. Это также предотвращает сбой приложения в случае изменения структуры JSON или отсутствия ожидаемых значений.

person Alpine    schedule 05.10.2014