1

現在、Openweathermap.org を使用して天気予報情報を取得しています。API から取得した JSON オブジェクトは次のとおりです。

{  
   "city":{  },
   "cod":"200",
   "message":0.0029,
   "cnt":40,
   "list":[  
      {  
         "dt":1466532000,
         "main":{  
            "temp":296.52,
            "temp_min":294.864,
            "temp_max":296.52,
            "pressure":1004.95,
            "sea_level":1023.45,
            "grnd_level":1004.95,
            "humidity":58,
            "temp_kf":1.65
         },
         "weather":[  
            {  
               "id":803,
               "main":"Clouds",
               "description":"broken clouds",
               "icon":"04d"
            }
         ],
         "clouds":{  },
         "wind":{  },
         "sys":{  },
         "dt_txt":"2016-06-21 18:00:00"
      },
      {  
         "dt":1466542800,
         "main":{  },
         "weather":[  ],
         "clouds":{  },
         "wind":{  },
         "sys":{  },
         "dt_txt":"2016-06-21 21:00:00"
      },
      {  
         "dt":1466553600,
         "main":{  },
         "weather":[  ],
         "clouds":{  },
         "wind":{  },
         "sys":{  },
         "dt_txt":"2016-06-22 00:00:00"
      }]
}

このサンプルからわかるように、リストの下には多くのオブジェクトがあり、私が必要としているのは、temp と weather のメインと説明だけです。すべての JSON オブジェクトを並べ替えて保持する構造体を作成しましたが、エラーが発生し続けます。「dt」でソートする方法と、JSON からデータを抽出する方法を教えてください。ありがとう。

ここに私の構造体があります:

import Foundation

struct FutureWeather {

 //future stuff
 var futureDt: NSDate //
 var futureMainWeather: String//
 var futureDescription: String//
 private var futureTemp: Double//
 var futureTempCelsius: Double {
    get {
        return futureTemp - 273.15
    }
 }
 var futureTempFahrenheit: Double {
    get {
        return (futureTemp - 273.15) * 1.8 + 32
    }
 }


init(futureWeatherData : [String:AnyObject]) {

    //first set of data
    let futureWeatherDictUno = futureWeatherData["list"]![0] as! [String: AnyObject]
    print(futureWeatherDictUno)

    let events = futureWeatherDictUno.sort({$0["dt"] <  $1["dt"]})

    futureDt = NSDate(timeIntervalSince1970: futureWeatherDictUno["dt"] as! NSTimeInterval)

    let mainDictOne = futureWeatherDictUno["main"] as! [String: AnyObject]
    futureTemp = mainDictOne["temp"] as! Double

    let weatherDictOne = futureWeatherDictUno["weather"]![0] as! [String: AnyObject]
    futureMainWeather = weatherDictOne["main"] as! String
    futureDescription = weatherDictOne["description"] as! String


    //the second set of data
    let futureWeatherDictDos = futureWeatherData["list"]![1] as! [String: AnyObject]
    futureDt = NSDate(timeIntervalSince1970: futureWeatherDictUno["dt"] as! NSTimeInterval)

    let mainDictTwo = futureWeatherDictDos["main"] as! [String: AnyObject]
    futureTemp = mainDictTwo["temp"] as! Double

    let weatherDictTwo = futureWeatherDictDos["weather"]![0] as! [String: AnyObject]
    futureMainWeather = weatherDictTwo["main"] as! String
    futureDescription = weatherDictTwo["description"] as! String


    }

}
4

2 に答える 2

1

配列をlist調べると、要素に基づいて JSON ファイル内の各要素が既に並べ替えられているはずですdt。また、配列内の各要素 ( futureWeatherData["list"]![0]) にはdtキー/値が 1 つしかないため、並べ替えることはできません。

あなたがすべきことは(これは単なる疑似コードです)は次のとおりです

let futureWeather = [Weather]() 
for element : JSON in array {
   let weather = Weather(json: element) //create weather element from json
   futureWeather.append(weather)
}

やりたくないことは、リスト内の各要素を、FutureWeather クラスの init メソッドで手動で調べることです。

https://github.com/SwiftyJSON/SwiftyJSONの使用を検討し、列挙型でキーを作成して json を通過することもお勧めします。

于 2016-06-22T13:59:42.910 に答える
0

@Asdrubal が回答で指摘したように、SwiftyJSON は便利なライブラリです。純粋な Foundation ソリューションが必要な場合はNSJSONSerialization、API データから応答を取得するために使用できます。気象データを取得するための将来の個人用サーバー側 Swift プロジェクトに先立って、この回答をここに投稿します:)

import Foundation

enum WeatherError: Int, ErrorType {
    /// The API response text could not be converted to an
    /// NSData object using NSUnicodeStringEncoding
    case UnexpectedAPITextEncoding = 1

    /// The API reponse object did not contain an array of
    /// Dictionary<String, AnyObject> objects at the "list"
    /// key
    case UnexpectedAPIResponseFormat = 2
}

/// An abstraction of a response to the OpenWeatherMap.org forecast API.
/// Contains only date, description and temperature data, plus convenience
/// properties to display temp in F or C.
///
/// NOTE: Each of the properties on the value are Optional, reflecting the
/// fact that the API response is sparsely populated for many of its values.
struct OpenWeatherMapResponse {

    /// The date of the forecast. Could be in the future
    let futureDt: NSDate?

    /// Textual description of the weather conditions for the forecast time
    let futureDescription: String?

    /// Temp provided in K
    private let futureTemp: Double?

    /// Temperature for the forecast time, in degrees C
    var futureTempCelsius: Double? {
        get {
            guard let futureTemp = futureTemp else {
                return nil
            }
            return futureTemp - 273.15
        }
    }

    /// Temperature for the forecast time, in degrees F
    var futureTempFahrenheit: Double? {
        get {
            guard let futureTemp = futureTemp else {
                return nil
            }
            return (futureTemp - 273.15) * 1.8 + 32
        }
    }

    /// Given a member of `list` from the API response,
    /// creates an OpenWeatherMapResponse
    init(jsonObject: AnyObject) {
        if let timestamp = jsonObject["dt"] as? NSTimeInterval {
            futureDt = NSDate(timeIntervalSince1970: timestamp)
        } else {
            futureDt = nil
        }

        if let mainBlock = jsonObject["main"] as? [String: AnyObject],
            temp = mainBlock["temp"] as? Double {
            futureTemp = temp
        } else {
            futureTemp = nil
        }

        if let weatherList = jsonObject["weather"] as? [AnyObject],
            description = weatherList.first?["description"] as? String {
            futureDescription = description
        } else {
            futureDescription = nil
        }
    }

    /// Given a JSON Object converted from an API response, parse the object
    /// into a collection of FutureWeather values.
    /// - throws: WeatherError if the API response text is in an unexpected character encoding or in
    /// an unexpected format
    /// - returns: an array of OpenWeatherMapResponse values
    static func responsesByConvertingAPIResponseString(apiResponseString: String) throws -> [OpenWeatherMapResponse] {

        // NSJSONSerialization only works on NSData. Convert it before using
        guard let apiData = apiResponseString.dataUsingEncoding(NSUnicodeStringEncoding) else {
            throw WeatherError.UnexpectedAPITextEncoding
        }

        // Convert API response data to a Foundation AnyObject
        let jsonObject = try NSJSONSerialization.JSONObjectWithData(apiData, options: [])

        var weatherList = [OpenWeatherMapResponse]()

        guard let events = jsonObject["list"] as? [[String: AnyObject]] else {
            throw WeatherError.UnexpectedAPIResponseFormat
        }

        for event in events {
            weatherList.append(OpenWeatherMapResponse(jsonObject: event))
        }

        return weatherList
    }

}


// API response
let jsonString = "{  \"city\":{  }, \"cod\":\"200\", \"message\":0.0029, \"cnt\":40, \"list\":[  {  \"dt\":1466532000, \"main\":{  \"temp\":296.52, \"temp_min\":294.864, \"temp_max\":296.52, \"pressure\":1004.95, \"sea_level\":1023.45, \"grnd_level\":1004.95, \"humidity\":58, \"temp_kf\":1.65 }, \"weather\":[  {  \"id\":803, \"main\":\"Clouds\", \"description\":\"broken clouds\", \"icon\":\"04d\" } ], \"clouds\":{  }, \"wind\":{  }, \"sys\":{  }, \"dt_txt\":\"2016-06-21 18:00:00\" }, {  \"dt\":1466542800, \"main\":{  }, \"weather\":[  ], \"clouds\":{  }, \"wind\":{  }, \"sys\":{  }, \"dt_txt\":\"2016-06-21 21:00:00\" }, {  \"dt\":1466553600, \"main\":{  }, \"weather\":[  ], \"clouds\":{  }, \"wind\":{  }, \"sys\":{  }, \"dt_txt\":\"2016-06-22 00:00:00\" }] }"

let weatherEvents = try OpenWeatherMapResponse.responsesByConvertingAPIResponseString(jsonString)

let sortedWeatherEvents = weatherEvents.sort() { a, b in a.futureDt?.timeIntervalSince1970 < b.futureDt?.timeIntervalSince1970 }

// prints:
// event: OpenWeatherMapResponse(futureDt: Optional(2016-06-21 18:00:00 +0000), futureDescription: Optional("broken clouds"), futureTemp: Optional(296.51999999999998))
// event: OpenWeatherMapResponse(futureDt: Optional(2016-06-21 21:00:00 +0000), futureDescription: nil, futureTemp: nil)
// event: OpenWeatherMapResponse(futureDt: Optional(2016-06-22 00:00:00 +0000), futureDescription: nil, futureTemp: nil)
for event in sortedWeatherEvents {
    print("event: \(event)")
}
于 2016-06-22T15:49:35.387 に答える