DrMac DrMac - 6 months ago 24x
Swift Question

How to parse JSON data properly if some data is NSNull

I'm currently pulling data via Twitter's Search API.

Once I receive the data, I am trying to parse and save the data to my TweetDetails class (which is to hold the author's name, the url of their profile pic, the text of the tweet, the location of the tweet, the tweet id and user id).

In some cases, the Tweets do not have a location (I think it has something to do if they're retweeted), and the certain dictionary (here being tweetsDict["place"]) that would otherwise hold that information, instead returns NSNull.

On those occasions, I receive this error

Could not cast value of type 'NSNull' (0x1093a1600) to 'NSDictionary' (0x1093a0fe8).

Here is my code as I am trying to parse the data and save it to objects in my TweetDetails class

client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
if connectionError != nil {
print("Error: \(connectionError)")
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: [])

if let tweets = json["statuses"] as? [NSDictionary] {
for tweetsDict in tweets {
let text = tweetsDict["text"] as! String
let tweetID = tweetsDict["id_str"] as! String
let place = tweetsDict["place"] as! NSDictionary

// this line ^^ is where the error occurs
let city = place.valueForKey("full_name")
let user = tweetsDict["user"] as! NSDictionary
let userID = user.valueForKey("id_str")
let screenName = user.valueForKey("screen_name")!
let avatarImage = user.valueForKey("profile_image_url_https")!

let tweet = TweetDetails(authors: screenName as! String, profileImages: avatarImage as! String, tweetTexts: text, tweetLocations: city as! String , tweetIDs: tweetID , userIDs: userID as! String)
} catch let jsonError as NSError {
print("json error: \(jsonError.localizedDescription)")

I have tried to create some 'if-let' statements to provide alternatives for these occasions, but nothing has worked.

Could someone please help me to create a custom alternative around when certain JSON data returns as NSNull. (Even something as simple as turning my "city" variable into the string "Unknown Location" in the cases when the data returns NSNull).

Thanks in advance and please let me know if there is anything else I can add to provide more clarity to this question.

Rob Rob

As others have pointed out, you can use optional binding (if let), or, in this case, even easier, just employ optional chaining:

let city = tweetsDict["place"]?["full_name"] as? String 

This way, city is an optional, i.e. if no value was found because there was no place or full_name entry, it will be nil.

It would appear, though, that your TweetDetails is force casting city to a String. Does it absolutely require a city? It would be best to change this method so that city was optional and gracefully handle nil values there. Alternatively, you can replace nil values for city to some other string, e.g. with the nil coalescing operator:

let city = tweetsDict["place"]?["full_name"] as? String ?? "Unknown city"

That returns the city if found, and "Unknown city" if not.