Swift JSOn解码错误:预期对Array <Any>进行解码,但找到了字典

时间:2019-09-06 08:46:15

标签: json swift

我有以下问题。 我向FatSecret API发送请求以获取食物的详细信息。 如果我解码通用食品,则可以使用,但是如果我获得品牌食品,则不能使用。

我的结构如下:

struct fatsecretFood : Decodable {
let food : Food

struct Food : Decodable {
    let brand_name: String?
    let food_id: String?
    let food_name: String?
    let food_type: String?
    let food_url: String?

    let servings : Servings

    struct Servings : Decodable {
        let serving : [Serving]

        struct Serving : Decodable {
            let serving_id: String?
            let serving_description: String?
            let serving_url: String?
            let metric_serving_amount: String?
            let metric_serving_unit: String?
            let number_of_units: String?
            let measurement_description: String?

            let calories: String?
            let carbohydrate: String?
            let protein: String?
            let fat: String?
            let saturated_fat: String?
            let polyunsaturated_fat: String?
            let monounsaturated_fat: String?
            let trans_fat: String?
            let cholesterol: String?
            let sodium: String?
            let potassium: String?
            let fiber: String?
            let sugar: String?
            let vitamin_a: String?
            let vitamin_c: String?
            let calcium: String?
            let iron: String?
        }
    }
}
}

代码行出现错误:

let data = Data(requestResponse.utf8)
    var foodDetails: fatsecretFood!
    var errors: fatsecretError!
    do {
        let result = try JSONDecoder().decode(fatsecretFood.self, from: data)
        foodDetails = result
    } catch { print(error) }
return foodDetails!

在那一次返回我得到错误:

typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "food", intValue: nil), CodingKeys(stringValue: "servings", intValue: nil), CodingKeys(stringValue: "serving", intValue: nil)], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))

示例通用食品(作品)的JSON如下:

{
  "food": {
  "food_id": "38884",
  "food_name": "Chocolate Chip Cookies (Soft Type)",
  "food_type": "Generic",
  "food_url": "https://www.fatsecret.com/calories-nutrition/usda/chocolate-chip-cookies-(soft-type)",
  "servings": {
     "serving": [
        {
           "calcium": "0",
           "calories": "130",
           "carbohydrate": "16.75",
           "cholesterol": "0",
           "fat": "6.89",
           "fiber": "0.9",
           "iron": "4",
           "measurement_description": "oz",
           "metric_serving_amount": "28.350",
           "metric_serving_unit": "g",
           "monounsaturated_fat": "3.695",
           "number_of_units": "1.000",
           "polyunsaturated_fat": "0.992",
           "potassium": "26",
           "protein": "0.99",
           "saturated_fat": "2.101",
           "serving_description": "1 oz",
           "serving_id": "38785",
           "serving_url": "https://www.fatsecret.com/calories-nutrition/usda/chocolate-chip-cookies-(soft-type)?portionid=38785&portionamount=1.000",
           "sodium": "92",
           "vitamin_a": "0",
           "vitamin_c": "0"
        },
        {
           "calcium": "0",
           "calories": "69",
           "carbohydrate": "8.86",
           "cholesterol": "0",
           "fat": "3.64",
           "fiber": "0.5",
           "iron": "2",
           "measurement_description": "cookie",
           "metric_serving_amount": "15.000",
           "metric_serving_unit": "g",
           "monounsaturated_fat": "1.955",
           "number_of_units": "1.000",
           "polyunsaturated_fat": "0.525",
           "potassium": "14",
           "protein": "0.52",
           "saturated_fat": "1.112",
           "serving_description": "1 cookie",
           "serving_id": "38786",
           "serving_url": "https://www.fatsecret.com/calories-nutrition/usda/chocolate-chip-cookies-(soft-type)?portionid=38786&portionamount=1.000",
           "sodium": "49",
           "vitamin_a": "0",
           "vitamin_c": "0"
        },
        {
           "calcium": "2",
           "calories": "458",
           "carbohydrate": "59.10",
           "cholesterol": "0",
           "fat": "24.30",
           "fiber": "3.2",
           "iron": "13",
           "measurement_description": "g",
           "metric_serving_amount": "100.000",
           "metric_serving_unit": "g",
           "monounsaturated_fat": "13.034",
           "number_of_units": "100.000",
           "polyunsaturated_fat": "3.500",
           "potassium": "93",
           "protein": "3.50",
           "saturated_fat": "7.411",
           "serving_description": "100 g",
           "serving_id": "61615",
           "serving_url": "https://www.fatsecret.com/calories-nutrition/usda/chocolate-chip-cookies-(soft-type)?portionid=61615&portionamount=100.000",
           "sodium": "326",
           "vitamin_a": "0",
           "vitamin_c": "0"
        }
     ]
  }
}
}

品牌食品示例的JSON(无效)如下:

{
 "food": {
   "brand_name": "Pepperidge Farm",
  "food_id": "61348",
  "food_name": "Soft Baked Sugar Cookies",
  "food_type": "Brand",
  "food_url": "https://www.fatsecret.com/calories-nutrition/pepperidge-farm/soft-baked-sugar-cookies",
  "servings": {
     "serving": {
        "calcium": "0",
        "calories": "140",
        "carbohydrate": "22",
        "cholesterol": "10",
        "fat": "5",
        "fiber": "0",
        "iron": "4",
        "measurement_description": "serving",
        "metric_serving_amount": "31.000",
        "metric_serving_unit": "g",
        "monounsaturated_fat": "1.5",
        "number_of_units": "1.000",
        "polyunsaturated_fat": "0.5",
        "protein": "2",
        "saturated_fat": "2.5",
        "serving_description": "1 cookie",
        "serving_id": "103910",
        "serving_url": "https://www.fatsecret.com/calories-nutrition/pepperidge-farm/soft-baked-sugar-cookies",
        "sodium": "90",
        "sugar": "11",
        "trans_fat": "0",
        "vitamin_a": "0",
        "vitamin_c": "0"
     }
  }
}
}

我没有找到错误。有人可以帮我吗? 谢谢

2 个答案:

答案 0 :(得分:1)

serving不是您在解码器中建议的Array。如JSON文件所示,它是另一个dictionary。尝试替换您的代码行:

let serving : [Serving] // before

let serving : Serving // after

如果serving是JSON中的数组,则看起来像这样:

"serving":[
    {  
        "calcium":"8",
        // ...
    },
    {
        "calcium":"10",
        // ...
    }
]

答案 1 :(得分:1)

请学习理解错误消息,这很容易阅读

  

typeMismatch(Swift.Array,Swift.DecodingError.Context(codingPath:[CodingKeys(stringValue:“ food”,intValue:nil),CodingKeys(stringValue:“ servings”,intValue:nil),CodingKeys(stringValue:“ servings”,intValue:nil) “,intValue:nil)],debugDescription:”预期对Array进行解码但是找到了一个字典。“,底层错误:nil))

  • typeMismatch表示您声明了错误的类型(Swift.Array<Any>)。
  • codingPath数组代表到受影响位置food/servings/serving的关键路径。
  • debugDescription Expected 部分描述了您的错误(数组),而 found 部分则描述了实际类型(字典,它是根据{ {1}}。

要能够同时解码数组和字典类型,您必须添加一个自定义初始化程序。 Codable的最终类型始终是数组。

serving

注意:

  • 名称结构始终以大写字母开头。
  • 不要使用 snake_cased 变量名。添加struct Servings : Decodable { let serving : [Serving] private enum CodingKeys : String, CodingKey { case serving } init(from decoder : Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) do { let servingDictionary = try container.decode(Serving.self, forKey: .serving) serving = [servingDictionary] } catch DecodingError.typeMismatch { serving = try container.decode([Serving].self, forKey: .serving) } } } 策略并声明 camelCased 名称。
  • 不要粗心地将所有内容声明为可选。似乎至少.convertFromSnakeCase对象总是发送所有键。