まず、リモートURLからデータを同期的にロードしないでくださいURLSession。常に、非同期メソッドを使用してください。
「Any」には添え字メンバーがありません
これは、コンパイラーが中間オブジェクトのタイプを認識していないため(たとえばcurrently、["currently"]!["temperature"])NSDictionary、コンパイラーのようにFoundationコレクションタイプを使用しているため、タイプについてまったく認識していません。
さらに、Swift 3では、すべての添え字付きオブジェクトのタイプについてコンパイラーに通知する必要があります。
JSONシリアル化の結果を実際の型にキャストする必要があります。
このコードはURLSession、Swiftネイティブ型のみを使用します
let urlString = "https://api.forecast.io/forecast/apiKey/37.5673776,122.048951"
let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
if error != nil {
print(error)
} else {
do {
let parsedData = try JSONSerialization.jsonObject(with: data!) as! [String:Any]
let currentConditions = parsedData["currently"] as! [String:Any]
print(currentConditions)
let currentTemperatureF = currentConditions["temperature"] as! Double
print(currentTemperatureF)
} catch let error as NSError {
print(error)
}
}
}.resume()
currentConditionsあなたが書くことができるすべてのキー/値のペアを印刷するには
let currentConditions = parsedData["currently"] as! [String:Any]
for (key, value) in currentConditions {
print("\(key) - \(value) ")
}
に関するメモjsonObject(with data:
多くの(すべてのように思われる)チュートリアルが提案する.mutableContainersか.mutableLeaves、Swiftではまったくナンセンスなオプションです。2つのオプションは、結果をNSMutable...オブジェクトに割り当てるための従来のObjective-Cオプションです。Swiftでは、すべてのvariableはデフォルトで変更可能であり、これらのオプションのいずれかを渡して結果をlet定数に割り当ててもまったく効果がありません。さらに、ほとんどの実装では、逆シリアル化されたJSONを変更することはありません。
スイフトに有用であるのみ(まれな)オプションがある.allowFragmentsJSONルートオブジェクトは値型とすることができる場合ならば必要とされる(String、Number、Boolまたはnull)ではなくコレクション・タイプのいずれか(arrayまたはdictionary)。ただし、通常は、オプションなしoptionsを意味するパラメーターを省略します。
================================================== =========================
JSONを解析するための一般的な考慮事項
JSONは適切に配置されたテキスト形式です。JSON文字列を読み取るのは非常に簡単です。文字列を注意深く読んでください。型は6つしかありません。2つのコレクション型と4つの値型です。
コレクションの種類は
- 配列 -JSON:大括弧内のオブジェクト
[]-Swift:[Any]ほとんどの場合[[String:Any]]
- 辞書 -JSON:中括弧内のオブジェクト
{}-Swift:[String:Any]
値のタイプは
- 文字列 -JSON:二重引用符
"Foo"で囲まれた任意の値、"123"または"false"- またはSwift:String
- 番号 - JSON:数値ではない二重引用符で
123か123.0-スウィフト:IntまたはDouble
- ブール - JSON:
trueかfalse いない二重引用符で-スウィフト:trueまたはfalse
- null -JSON:
null– Swift:NSNull
JSON仕様によれば、辞書のすべてのキーはである必要がありますString。
基本的には、オプションのバインディングを使用してオプションを安全にアンラップすることを常にお勧めします
ルートオブジェクトが辞書({})の場合、型を[String:Any]
if let parsedData = try JSONSerialization.jsonObject(with: data!) as? [String:Any] { ...
キーで値を取得します(OneOfSupportedJSONTypes上記のように、JSONコレクションまたは値のタイプです)。
if let foo = parsedData["foo"] as? OneOfSupportedJSONTypes {
print(foo)
}
ルートオブジェクトが配列([])の場合、型を[[String:Any]]
if let parsedData = try JSONSerialization.jsonObject(with: data!) as? [[String:Any]] { ...
と配列を繰り返します
for item in parsedData {
print(item)
}
特定のインデックスのアイテムが必要な場合は、インデックスが存在するかどうかも確認してください
if let parsedData = try JSONSerialization.jsonObject(with: data!) as? [[String:Any]], parsedData.count > 2,
let item = parsedData[2] as? OneOfSupportedJSONTypes {
print(item)
}
}
JSONがコレクションタイプではなく、単に値タイプの1つであるまれなケースでは、.allowFragmentsオプションを渡して、結果を適切な値タイプにキャストする必要があります。
if let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? String { ...
AppleはSwiftブログで包括的な記事を公開しています:Swift でのJSONの操作
================================================== =========================
Swift 4以降では、CodableプロトコルはJSONを直接構造体/クラスに解析するより便利な方法を提供します。
たとえば、質問で指定されたJSONサンプル(わずかに変更)
let jsonString = """
{"icon": "partly-cloudy-night", "precipProbability": 0, "pressure": 1015.39, "humidity": 0.75, "precip_intensity": 0, "wind_speed": 6.04, "summary": "Partly Cloudy", "ozone": 321.13, "temperature": 49.45, "dew_point": 41.75, "apparent_temperature": 47, "wind_bearing": 332, "cloud_cover": 0.28, "time": 1480846460}
"""
構造体にデコードできますWeather。Swiftタイプは上記と同じです。追加のオプションがいくつかあります。
- を表す文字列は、
URLとして直接デコードできますURL。
time整数として復号することができるDateとdateDecodingStrategy .secondsSince1970。
- snaked_cased JSONキーをキャメルケースに変換するには、
keyDecodingStrategy .convertFromSnakeCase
struct Weather: Decodable {
let icon, summary: String
let pressure: Double, humidity, windSpeed : Double
let ozone, temperature, dewPoint, cloudCover: Double
let precipProbability, precipIntensity, apparentTemperature, windBearing : Int
let time: Date
}
let data = Data(jsonString.utf8)
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(Weather.self, from: data)
print(result)
} catch {
print(error)
}
その他のコード化可能なソース: