स्विफ्ट 3 का उपयोग कर JSON डेटा को पार्स करते समय मैंने एक अजीब व्यवहार अनुभव किया है।
do {
let json = try JSONSerialization.jsonObject(with: data!, options: []) as! NSDictionary
let items:[AnyObject] = (json["items"] as? [AnyObject])!
for item in items {
let id:String = item["id"] as! String
print("ID: (id)")
let info = item["volumeInfo"] as AnyObject
print(info)
let title = info["title"]
print(title)
}
} catch {
print("error thrown")
}
यह निम्नलिखित आउटपुट पैदा करता है। ध्यान दें कि जानकारी एक वैकल्पिक है, लेकिन अगर मैं इसे खोलने की कोशिश करता हूं तो यह कहता है कि यह वैकल्पिक नहीं है! लिपि पर दुर्घटनाग्रस्त हो जाता है let title = info["title"]
नतीजतन मैं शीर्षक कुंजी तक नहीं पहुंच सकता। यह व्यवहार स्विफ्ट 2 के बाद बदल गया है।
ID: lbvUD6LUyV8C
Optional({
publishedDate = 2002;
publisher = "Sams Publishing";
title = "Java Deployment with JNLP and WebStart";
})
उत्तर:
जवाब के लिए 0 № 1आप कुछ ऐसा कर सकते हैं:
do {
let json = try JSONSerialization.jsonObject(with: data!) as! [String: Any]
let items = json["items"] as! [[String: Any]]
for item in items {
let id = item["id"] as! String
let info = item["volumeInfo"] as! [String: Any]
let title = info["title"] as! String
print(id)
print(info)
print(title)
}
} catch {
print("error thrown: (error)")
}
मैं कोड के उत्साह का सुझाव दे सकता हूं !
मजबूर करने के लिए मजबूर होना (यदि JSON आपके द्वारा अपेक्षित रूप में नहीं था, तो क्या आप वास्तव में इसे क्रैश करना चाहते हैं?), लेकिन उम्मीद है कि यह मूल विचार को दर्शाता है।
जवाब के लिए 0 № 2
रनटाइम प्रकार का info
है Optional<Something>
, लेकिन संकलन समय प्रकार (जैसा कि आपने स्पष्ट रूप से इसे कास्ट किया है) है AnyObject
। संकलक को यह कैसे पता होना चाहिए कि AnyObject
एक होना होगा Optional<Something>
जब तक आप इसे नहीं बताते (एक कास्ट के रूप में)?
प्रयत्न:
let info = item["volumeInfo"] as AnyObject?
अब संकलक जानता है कि यह एक है Optional<AnyObject>
, तो आप इसे खोल सकते हैं।
जवाब के लिए 0 № 3
स्विफ्ट 3 में कंपाइलर को सभी सबस्क्रिप्टेड ऑब्जेक्ट्स के प्रकारों को जानना चाहिए यदि यह एक सरणी या शब्दकोश है। AnyObject
- जो बदल दिया गया है Any
स्विफ्ट 3 में - पर्याप्त नहीं है।
चूंकि आप जानते हैं कि कुंजी के लिए मूल्य volumeInfo
एक शब्दकोश है जो वैकल्पिक रूप से वैकल्पिक बाइंडिंग का उपयोग करके इसे कास्ट करता है
let info = item["volumeInfo"] as? [String:Any] {
print(info)
let title = info["title"] as! String
print(title)
}
जवाब के लिए 0 № 4
यह करना चाहिए:
guard let json = try? JSONSerialization.jsonObject(with: data!, options: []) as! [String: AnyObject],
let items = json["items"] as! Array<AnyObject>? else {
return
}
for item in items {
let id = item["id"] as! String
if let info = item["volumeInfo"] as? [String: AnyObject] {
let title = info["title"] as! String
} else {
// do something
}
}