Swift return type for NSJSONSerialization.JSONObjectWithData() is unintuitive, impractical
| Originator: | invalidname | ||
| Number: | rdar://17499931 | Date Originated: | 6/29/14 |
| Status: | open | Resolved: | |
| Product: | iOS SDK | Product Version: | iOS 8 beta 2 / Xcode 6 beta 2 |
| Classification: | other bug | Reproducible: | always |
Summary:
In Obj-C, -[NSJSONSerialization JSONObjectWithData] returns id, and the docs indicate it will be a Foundation type, meaning either NSArray or NSDictionary.
In Swift, this returns arrays or dictionaries of unexpected types that are burdensome to unbundle. Specifically:
1. The object can be cast to Array<Dictionary<String,AnyObject>> (or Dictionary<String,AnyObject>[]), but not Array<Dictionary<String,Any>>.
2. When the value of a given name-value pair in the dictionary is a string, it cannot be cast to a Swift string (this causes a compiler error). It must be retrieved as an AnyObject? and then cast to a Swift String, or retrieved as an NSString.
Steps to Reproduce:
Run the sample project NSJSONSerializationSwiftBuglet. It reads a bundled JSON file as NSData (the results of performing an SLRequest to read a Twitter timeline), uses NSJSONSerialization.JSONObjectWithData to create an AnyObject? called jsonData, and then attempts various techniques to get at the contents of the JSON object. These techniques log messages to a UITextView.
Expected Results:
The data is an array of dictionaries, which are keyed with strings and can have either arrays, dictionaries, or strings as values… so I would expect to be able to cast to NSArray<NSDictionary<String, Any>>, since the Swift string is not an object, per se.
Actual Results:
Here's the output:
got a jsonObject
----------------
----------------
it's not an Array<Dictionary<String,Any>>
----------------
it's an Array<Dictionary<String,AnyObject>>
* First Tweet: RT @edbott: No. Just no. RT @ow The future on your wrist http://t.co/ecIs4co62J
* Roundabout NSString technique works here
----------------
it's a Dictionary<String,AnyObject>[]
* First Tweet: RT @edbott: No. Just no. RT @ow The future on your wrist http://t.co/ecIs4co62J
* Roundabout NSString technique works here
----------------
it's an Array<AnyObject>
first object is a Dictionary <String, AnyObject>
* First Tweet: RT @edbott: No. Just no. RT @ow The future on your wrist http://t.co/ecIs4co62J
* Roundabout NSString technique works here
----------------
it's not an Array<Any>
no further tests here, I'm lazy
----------------
it's an NSArray
no further tests here, I'm lazy
----------------
Points of interest:
1. I *cannot* cast the jsonObject to Array<Dictionary<String,Any>>, though I can cast it to Array<Dictionary<String,AnyObject>>. Why would the more general cast fail, and the more specific cast succeed?
2. I would expect to be able to cast the value of a name-value pair to a string optional ("String?") like this:
let tweetText : String? = tweetDict["text"] as? String
however, if the jsonObject was cast to Array<Dictionary<String,AnyObject>>, the compiler rejects this line as "Could not find an overload for 'subscript' that accepts the supplied arguments". OTOH, this line compiles when jsonObject was cast to Array<Dictionary<String,Any>>, but that block never executes anyways.
3. Casting values to NSStrings instead of Swift strings seems to always compile and always work.
Version:
Xcode 6 beta 2, OS X 10.9.3
Notes:
My main complaints are that
1. Casting the jsonObject to Array<Dictionary<String,Any>> is the intuitive choice and should work.
2. In the Array<Dictionary<String,AnyObject>> case, getting the value from the dictionary with "let tweetText : String? = tweetDict["text"] as? String" is the intuitive way to get a Swift string and should compile (and would, if point 1 were true). The compiler error here is also unhelpful.
Configuration:
Early 2008 Mac Pro
Attachments:
'NSJSONSerializationSwiftBuglet.zip' was successfully uploaded.
OpenRadar readers: buglet code at https://dl.dropboxusercontent.com/u/12216224/buglets/NSJSONSerializationSwiftBuglet.zip
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!