我有以下问题。 我向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"
}
}
}
}
我没有找到错误。有人可以帮我吗? 谢谢
答案 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
注意:
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
对象总是发送所有键。