सबसे पहले कभी भी किसी दूरस्थ URL से डेटा लोड न करें , हमेशा अतुल्यकालिक तरीकों का उपयोग करें URLSession
।
'किसी' के कोई सदस्य नहीं हैं
इसलिए होती है क्योंकि संकलक जो भी लिखते मध्यवर्ती वस्तुओं (उदाहरण के लिए कर रहे हैं का पता नहीं है currently
में ["currently"]!["temperature"]
) और जैसे आप फाउंडेशन संग्रह प्रकार का उपयोग किया जाता है क्योंकि NSDictionary
संकलक प्रकार के बारे में सब पर कोई विचार है।
इसके अतिरिक्त स्विफ्ट 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
:
कई (यह सब लगता है) ट्यूटोरियल सुझाव .mutableContainers
या .mutableLeaves
विकल्प जो स्विफ्ट में पूरी तरह से बकवास है। NSMutable...
ऑब्जेक्ट के लिए परिणाम असाइन करने के लिए दो विकल्प लीगेसी ऑब्जेक्टिव-सी विकल्प हैं। स्विफ्ट में किसी भी var
iable को डिफ़ॉल्ट रूप से म्यूट किया जाता है और उन विकल्पों में से किसी को भी पास किया जाता है और परिणाम को let
स्थिर करने का कोई प्रभाव नहीं पड़ता है। इसके अलावा अधिकांश कार्यान्वयन कभी भी deserialized JSON को म्यूट नहीं कर रहे हैं।
केवल (दुर्लभ) विकल्प जो स्विफ्ट में उपयोगी है है .allowFragments
जो करता है, तो अगर JSON जड़ वस्तु एक मान प्रकार हो सकता है की आवश्यकता होती है ( String
, Number
, Bool
या null
) के बजाय संग्रह प्रकारों में से एक ( array
या dictionary
)। लेकिन आम तौर पर options
पैरामीटर को छोड़ दें जिसका अर्थ है कोई विकल्प नहीं ।
================================================== =========================
JSON को पार्स करने के लिए कुछ सामान्य विचार
JSON एक अच्छी तरह से व्यवस्थित पाठ प्रारूप है। JSON स्ट्रिंग पढ़ना बहुत आसान है। स्ट्रिंग को ध्यान से पढ़ें । केवल छह अलग-अलग प्रकार हैं - दो संग्रह प्रकार और चार मूल्य प्रकार।
संग्रह प्रकार हैं
- ऐरे - JSON: स्क्वायर ब्रैकेट में ऑब्जेक्ट्स
[]
- स्विफ्ट: [Any]
लेकिन ज्यादातर मामलों में[[String:Any]]
- शब्दकोश - JSON: घुंघराले ब्रेसिज़ में वस्तुएँ
{}
- स्विफ्ट:[String:Any]
मान प्रकार हैं
- स्ट्रिंग - JSON: दोहरे उद्धरण में कोई मूल्य
"Foo"
, यहां तक कि "123"
या "false"
- स्विफ्ट:String
- संख्या - JSON: संख्यात्मक मान नहीं दोहरे उद्धरण में
123
या 123.0
- स्विफ्ट: Int
याDouble
- बूल - JSON:
true
या दोहरे उद्धरणों में false
नहीं - स्विफ्ट: true
याfalse
- null - JSON:
null
- स्विफ्ट: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 ने स्विफ्ट ब्लॉग में एक व्यापक लेख प्रकाशित किया है: स्विफ्ट में JSON के साथ कार्य करना
================================================== =========================
स्विफ्ट 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
। स्विफ्ट प्रकार समान हैं जो ऊपर वर्णित हैं। कुछ अतिरिक्त विकल्प हैं:
- एक का प्रतिनिधित्व करने वाले स्ट्रिंग्स को
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)
}
अन्य कोड करने योग्य स्रोत: