우선 원격 URL에서 동 기적으로 데이터를로드하지 , 항상 같은 비동기 방법을 사용합니다 URLSession
.
'Any'에는 아래 첨자 멤버가 없습니다.
컴파일러가 중간 오브젝트 (예를 들어 있습니다 입력 한 내용의 아무 생각이 없기 때문에 발생 currently
에서 ["currently"]!["temperature"]
)와 같은 당신이 재단 수집 유형을 사용하기 때문에 NSDictionary
컴파일러가 타입에 대해 전혀 모르고있다가.
또한 Swift 3에서는 모든 첨자 된 객체 의 유형에 대해 컴파일러에 알려야 합니다.
JSON 직렬화의 결과를 실제 유형으로 캐스팅해야합니다.
이 코드 사용 URLSession
및 전용 스위프트 기본 유형
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
:
많은 (모두 보이는) 튜토리얼 이 Swift에서 완전히 말도 안되는 옵션 .mutableContainers
이나 제안을 제안 .mutableLeaves
합니다. 두 가지 옵션은 결과를 NSMutable...
개체 에 할당하는 레거시 Objective-C 옵션 입니다. Swift에서 모든 var
iable은 기본적으로 변경 가능하며 이러한 옵션 중 하나를 전달하고 결과를 let
상수에 할당 해도 전혀 효과가 없습니다. 더 나아가 대부분의 구현은 어쨌든 역 직렬화 된 JSON을 변경하지 않습니다.
Swift에서 유용한 유일한 (희귀 한) 옵션 .allowFragments
은 JSON 루트 객체가 컬렉션 유형 ( 또는 ) 중 하나가 아닌 값 유형 ( , 또는 ) String
일 수있는 경우에 필요한 옵션입니다 . 그러나 일반적으로 옵션 없음 을 의미 하는 매개 변수를 생략합니다 .Number
Bool
null
array
dictionary
options
================================================ =========================
JSON 구문 분석에 대한 몇 가지 일반적인 고려 사항
JSON은 잘 정렬 된 텍스트 형식입니다. JSON 문자열을 읽는 것은 매우 쉽습니다. 문자열을주의 깊게 읽으십시오 . 컬렉션 유형 2 개와 값 유형 4 개 등 6 가지 유형 만 있습니다.
컬렉션 유형은 다음과 같습니다.
- 배열 -JSON : 대괄호 안의 객체
[]
-Swift : [Any]
그러나 대부분의 경우[[String:Any]]
- 사전 -JSON : 중괄호 안의 객체
{}
-Swift :[String:Any]
값 유형은 다음과 같습니다.
- 문자열 -JSON : 큰 따옴표로 묶인 모든 값
"Foo"
, 짝수 "123"
또는 "false"
– Swift :String
- 숫자 -JSON : 큰 따옴표가 없는 숫자 값
123
또는 123.0
– Swift : Int
또는Double
- Bool -JSON :
true
또는 큰 따옴표로 묶지 false
않음 – Swift : 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이 컬렉션 유형이 아니라 값 유형 중 하나 인 경우 .allowFragments
옵션 을 전달 하고 결과를 적절한 값 유형으로 캐스팅해야합니다.
if let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? String { ...
Apple은 Swift Blog : Working with JSON in Swift에 포괄적 인 기사를 게시했습니다.
================================================ =========================
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}
"""
struct로 디코딩 할 수 있습니다 Weather
. Swift 유형은 위에서 설명한 것과 동일합니다. 몇 가지 추가 옵션이 있습니다.
- 를 나타내는 문자열
URL
로 직접 디코딩 할 수있다 URL
.
time
정수로 디코딩 될 수 Date
와 dateDecodingStrategy
.secondsSince1970
.
- snaked_cased JSON 키는 다음을 사용하여 camelCase 로 변환 할 수 있습니다 .
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)
}
기타 코딩 가능한 소스 :