0

I am trying to parse JSON data to a dictionary, for parsing I am using the separate method, and later would like to use the results (dictionary) for other operations in another method, not just to print it out as it is given in many examples online, e. g. here.

However, I cannot return the value since I was asked to insert return statement inside guard, but after the insertion getting "Non-void function should return a value".

The code looks the following way:

 func  extractJSONDictionaryFrom(JSONData:NSData) ->NSMutableDictionary
    {
        var dict = NSMutableDictionary()
        do {
        guard let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:NSJSONReadingOptions(rawValue: 0)) as? NSDictionary else {
            print("Not a Dictionary")
            return
        }
            dict = NSMutableDictionary(dictionary: JSON)
        }
        catch let JSONError as NSError {
            print("\(JSONError)")
        }
        print("The JSON is \(dict)")
        return dict
    }

The approach using throw is as well hardly useful since I need to handle throws in other methods when calling "extractJSONDictionaryFrom"

4

2 回答 2

1

One option, is to let your method throw errors (whether the NSJSONSerialization error because JSON parsing failed entirely or your custom error if JSON parsing worked, but it wasn't a dictionary for some reason):

func extractJSONDictionaryFrom(JSONData: NSData) throws -> NSMutableDictionary {
    guard let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:[]) as? NSDictionary else {
        throw NSError(domain: NSBundle.mainBundle().bundleIdentifier!, code: -1, userInfo: [NSLocalizedDescriptionKey : "Not a dictionary"])
    }
    return NSMutableDictionary(dictionary: JSON)
}

Or, another approach is to not have it throw errors, but just return nil if the conversion failed:

func extractJSONDictionaryFrom(JSONData: NSData) -> NSMutableDictionary? {
    do {
        guard let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:NSJSONReadingOptions(rawValue: 0)) as? NSDictionary else {
            print("Not a Dictionary")
            return nil
        }
        return NSMutableDictionary(dictionary: JSON)
    } catch let JSONError as NSError {
        print("\(JSONError)")
        return nil
    }
}

I'd lean towards the former, but the latter works, too.

于 2016-01-19T08:49:44.790 回答
1

Make the result optional (NSMutableDictionary?) and use return nil.

You might also want to return NSDictionary? if the caller should not change the returned dictionary.

EDIT

The code given does not work as NSJSONSerialization.JSONObjectWithData throws an error given invalid JSON and this is caught by the catch. The function returns an empty dictionary and not nil. I would try the following:

func  extractJSONDictionaryFrom(JSONData:NSData) ->NSMutableDictionary?
{
    var dict = NSMutableDictionary()
    do {
        guard let JSON = try NSJSONSerialization.JSONObjectWithData(JSONData, options:NSJSONReadingOptions(rawValue: 0)) as? NSDictionary else {
            print("Not a Dictionary")
            return nil
        }
        dict = NSMutableDictionary(dictionary: JSON)
    }
    catch let JSONError as NSError {
        print("\(JSONError)")
        return nil
    }
    print("The JSON is \(dict)")
    return dict
}

I also believe that propagating the exception would be better.

Alternatively, you could return an empty dictionary for all errors and not use an optional result, but this "hides" errors which is probably a bad idea.

于 2016-01-19T08:53:06.133 回答