2015-12-08 35 views
1

我對iOS開發非常陌生,我有一個問題來解析來自API的JSON響應。解決JSON的Swift問題:無法將'__NSCFDictionary'類型的值轉換爲'NSArray'錯誤

這裏是我的示例JSON看起來像:

{ 
"recipe":{ 
"publisher":"Real Simple", 
"f2f_url":"http://food2fork.com/view/39999", 
"ingredients":[ 
    "1 tablespoon olive oil", 
    "1 red onion, chopped", 
    "2 small yellow squash, cut into 1/2-inch pieces", 
    "2 cloves garlic, chopped", 
    "1 jalapeo, seeded and thinly sliced", 
    "1 kosher salt and black pepper", 
    "4 28-ounce can diced tomatoes\n" 
], 
"source_url":"http://www.realsimple.com/food-recipes/browse-all-recipes/halibut-spicy-squash-tomatoes-00000000006842/index.html", 
"recipe_id":"39999", "image_url":"http://static.food2fork.com/someurl.jpg", 
    "social_rank":95.14721536803285, 
    "publisher_url":"http://realsimple.com", 
    "title":"Halibut With Spicy Squash and Tomatoes" 
    } 
} 

,當我打印JSON(另一個在這個例子中)它看起來像這樣:

["recipe": { 
    "f2f_url" = "http://food2fork.com/view/20970"; 
    "image_url" = "http://static.food2fork.com/98113574b0.jpg"; 
    ingredients =  (
    "1 (170 gram) can crabmeat", 
    "125 grams PHILADELPHIA Light Brick Cream Cheese Spread, softened", 
    "2 green onions, thinly sliced", 
    "1/4 cup MIRACLE WHIP Calorie-Wise Dressing", 
    "12 wonton wrappers" 
); 
    publisher = "All Recipes"; 
    "publisher_url" = "http://allrecipes.com"; 
    "recipe_id" = 20970; 
    "social_rank" = "41.83825995815504"; 
    "source_url" = "http://allrecipes.com/Recipe/Philly-Baked-Crab-Rangoon/Detail.aspx"; 
    title = "PHILLY Baked Crab Rangoon"; 
}] 

我有一個對象配方和它看起來像這樣:

class Recipe { 
    struct Keys { 
     static let Title = "title" 
     static let ImageUrl = "image_url" 
     static let Ingredients = "ingredients" 
     static let RecipeId = "recipe_id" 
    } 

    var title : String? = nil 
    var id = 0 
    var imageUrl : String? = nil 
    var ingredients : String? = nil 

    init(dictionary : NSDictionary) { 
     self.title = dictionary[Keys.Title] as? String 
     self.id = dictionary[RecipeDB.Keys.ID] as! Int 
     self.imageUrl = dictionary[Keys.ImageUrl] as? String 
     self.ingredients = dictionary[Keys.Ingredients] as? String 
    } 
} 

當我嘗試解析JSON並將其轉換爲字典時,我得到一個這裏錯誤

是我的方法是投響應字典和導致錯誤

func recipiesFromData(data: NSData) -> [Recipe] { 

    var dictionary : [String : AnyObject]! 

    dictionary = (try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments)) 
    as! [String : AnyObject] 

    let recipeDictionaries = dictionary["recipe"] as! [[String : AnyObject]] 

    let recipies = recipeDictionaries.map() { Recipe(dictionary: $0) } 

    return recipies 
} 

感謝。

+0

這看起來不像是有效的JSON – njuri

+0

這不是原始的JSON,看起來像一個'print'解析後的JSON。 – Rob

+0

爲什麼要將nsdictionary轉換爲nsarray? –

回答

1

如果這是你的JSON(單一配方),解析代碼看起來像:

func recipeFromData(data: NSData) -> Recipe { 
    let dictionary = (try! NSJSONSerialization.JSONObjectWithData(data, options: [])) as! [String : [String : AnyObject]] 

    return Recipe(dictionary: dictionary["recipe"]!) 
} 

我會捏捏Recipe類如下:

class Recipe { 
    struct Keys { 
     static let Title = "title" 
     static let ImageUrl = "image_url" 
     static let Ingredients = "ingredients" 
     static let RecipeId = "recipe_id" 
    } 

    var title: String? 
    var id: Int 
    var imageUrl: String? 
    var ingredients: [String]? 

    init(dictionary : [String : AnyObject]) { 
     self.title = dictionary[Keys.Title] as? String 
     self.id = Int(dictionary[Keys.RecipeId] as! String)! 
     self.imageUrl = dictionary[Keys.ImageUrl] as? String 
     self.ingredients = dictionary[Keys.Ingredients] as? [String] 
    } 
} 

這應該解析JSON。


就個人而言,我會刪除所有這些!的,因爲如果有什麼錯誤,它會崩潰。例如:

enum RecipeError: ErrorType { 
    case InvalidJSON(message: String, userInfo: [NSObject: AnyObject]) 
    case MalformedJSON 
    case RecipeKeyNotFound 
    case BadKeysValues 
} 

func recipeFromData(data: NSData) throws -> Recipe { 
    var jsonObject: AnyObject 

    do { 
     jsonObject = try NSJSONSerialization.JSONObjectWithData(data, options: []) 
    } catch let parseError as NSError { 
     throw RecipeError.InvalidJSON(message: parseError.localizedDescription, userInfo: parseError.userInfo) 
    } 

    guard let dictionary = jsonObject as? [String : AnyObject] else { 
     throw RecipeError.MalformedJSON 
    } 

    guard let recipeDictionary = dictionary["recipe"] as? [String: AnyObject] else { 
     throw RecipeError.RecipeKeyNotFound 
    } 

    guard let recipe = Recipe(dictionary: recipeDictionary) else { 
     throw RecipeError.BadKeysValues 
    } 

    return recipe 
} 

無論你去到這種極端的只是一個你想要什麼樣的錯誤,才能夠正常拍攝,但希望這說明了一點,要避免使用強制展開(問題與!as!)如果處理您從遠程源獲得的數據可能會引入問題,您的應用程序必須預測並妥善處理,而不是隻是崩潰。

順便說一句,在上面的例子中,我給了Recipe一個failable初始化:

struct Recipe { 
    struct Keys { 
     static let Title = "title" 
     static let ImageUrl = "image_url" 
     static let Ingredients = "ingredients" 
     static let RecipeId = "recipe_id" 
    } 

    let title: String? 
    let id: Int 
    let imageUrl: String? 
    let ingredients: [String]? 

    init?(dictionary : [String : AnyObject]) { 
     if let idString = dictionary[Keys.RecipeId] as? String, let id = Int(idString) { 
      self.id = id 
     } else { 
      return nil 
     } 
     self.title = dictionary[Keys.Title] as? String 
     self.imageUrl = dictionary[Keys.ImageUrl] as? String 
     self.ingredients = dictionary[Keys.Ingredients] as? [String] 
    } 
} 

(注意,我做了這個struct,因爲它支持更直觀failable初始化如果你想有一個failable初始化器,它需要你在失敗之前初始化所有的東西(這對我來說似乎是非常直觀的)

+0

謝謝,這對我很有用。 –

0

下面是有效的JSON,它完美地轉換爲[String : AnyObject]

let string = "{\"recipe\":{\"f2f_url\":\"http://food2fork.com/view/20970\",\"image_url\":\"http://static.food2fork.com/98113574b0.jpg\",\"ingredients\":[\"1 (170 gram) can crabmeat\",\"125 grams PHILADELPHIA Light Brick Cream Cheese Spread, softened\",\"2 green onions, thinly sliced\",\"1/4 cup MIRACLE WHIP Calorie-Wise Dressing\",\"12 wonton wrappers\"],\"publisher\":\"All Recipes\",\"publisher_url\":\"http://allrecipes.com\",\"recipe_id\":20970,\"social_rank\":\"41.83825995815504\",\"source_url\":\"http://allrecipes.com/Recipe/Philly-Baked-Crab-Rangoon/Detail.aspx\",\"title\":\"PHILLY Baked Crab Rangoon\"}}" 

do{ 
    let dict = try NSJSONSerialization.JSONObjectWithData(string.dataUsingEncoding(NSUTF8StringEncoding)!, options:NSJSONReadingOptions.AllowFragments) as! [String : AnyObject] 
    print(dict) 
} catch let error as NSError{ 
    print(error.localizedDescription) 
} 
相關問題