我正在我的Swift应用程序中解码一个JSON响应,当我切换api URL时,代码决定不工作。
这是我的json回应
{
"totalHits":396990,
"currentPage":1,
"totalPages":396990,
"pageList":[
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
],
"foodSearchCriteria":{
"dataType":[
],
"pageNumber":1,
"numberOfResultsPerPage":50,
"pageSize":1,
"requireAllWords":false
},
"foods":[
{
"fdcId":1104067,
"description":"100 GRAND Bar",
"lowercaseDescription":"100 grand bar",
"commonNames":"",
"additionalDescriptions":"$ 100,000 Bar",
"dataType":"Survey (FNDDS)",
"foodCode":91715300,
"publishedDate":"2020-10-30",
"foodCategory":"Candy containing chocolate",
"foodCategoryId":999786,
"allHighlightFields":"",
"score":1.0,
"foodNutrients":[
{
"nutrientId":1003,
"nutrientName":"Protein",
"nutrientNumber":"203",
"unitName":"G",
"value":2.5,
"rank":600,
"indentLevel":1,
"foodNutrientId":13301423
},
{
"nutrientId":1280,
"nutrientName":"PUFA 22:5 n-3 (DPA)",
"nutrientNumber":"631",
"unitName":"G",
"value":0.0,
"rank":15200,
"indentLevel":2,
"foodNutrientId":13301485
},
{
"nutrientId":1292,
"nutrientName":"Fatty acids, total monounsaturated",
"nutrientNumber":"645",
"unitName":"G",
"value":6.04,
"rank":11400,
"indentLevel":1,
"foodNutrientId":13301486
},
{
"nutrientId":1293,
"nutrientName":"Fatty acids, total polyunsaturated",
"nutrientNumber":"646",
"unitName":"G",
"value":1.39,
"rank":12900,
"indentLevel":1,
"foodNutrientId":13301487
}
],
"finalFoodInputFoods":[
{
"foodDescription":"Candies, NESTLE, 100 GRAND Bar",
"gramWeight":100,
"id":102104,
"portionCode":"0",
"portionDescription":"NONE",
"unit":"GM",
"rank":1,
"srCode":19144,
"value":100
}
],
"foodMeasures":[
{
"disseminationText":"1 bar (1.5 oz)",
"gramWeight":43,
"id":246540,
"modifier":"60362",
"rank":1,
"measureUnitAbbreviation":"undetermined",
"measureUnitName":"undetermined",
"measureUnitId":9999
},
{
"disseminationText":"Quantity not specified",
"gramWeight":21,
"id":266827,
"modifier":"90000",
"rank":2,
"measureUnitAbbreviation":"undetermined",
"measureUnitName":"undetermined",
"measureUnitId":9999
}
],
"foodAttributes":[
],
"foodAttributeTypes":[
{
"name":"Additional Description",
"description":"Additional descriptions for the food.",
"id":1001,
"foodAttributes":[
{
"value":"$ 100,000 Bar",
"id":978293,
"sequenceNumber":1
}
]
},
{
"name":"Attribute",
"description":"Generic attributes",
"id":999,
"foodAttributes":[
{
"value":"5702",
"name":"WWEIA Category number",
"id":991595
},
{
"value":"Candy containing chocolate",
"name":"WWEIA Category description",
"id":999786
}
]
}
],
"foodVersionIds":[
]
}
],
"aggregations":{
"dataType":
我正面临着这个错误
Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "foods", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"foods\", intValue: nil) (\"foods\").", underlyingError: nil))
我想这是因为我的“食物”没有正确匹配,但看起来并不是这样。下面我附加了我的调用和结构的片段。
struct APISearchResults: Codable {
let currentPage, totalPages: Int?
let pageList: [Int]?
//let foodSearchCriteria: FoodSearchCriteria
let foods: [Food]
}
// MARK: - Food
struct Food: Codable { //core
let fdcID: Int
let foodDescription, lowercaseDescription, commonNames, additionalDescriptions: String?
let dataType: String?
let ndbNumber: Int?
let publishedDate, foodCategory, allHighlightFields: String?
let score: Double?
let foodNutrients: [FoodNutrientInformation]
let gtinUpc: Double?
let brandOwner: String?
let ingredients: String?
let marketCountry: String?
let modifiedDate: String?
let dataSource: String?
let servingSize: Double?
let householdServingFullText: String?
enum CodingKeys: String, CodingKey {
case fdcID = "fdcId"
case foodDescription = "description"
case lowercaseDescription, commonNames, additionalDescriptions, dataType, ndbNumber, publishedDate, foodCategory, allHighlightFields, score, foodNutrients, gtinUpc, brandOwner, ingredients, marketCountry, modifiedDate, dataSource, servingSize, householdServingFullText
}
}
// MARK: - FoodNutrient
struct FoodNutrientInformation: Codable {
let nutrientID: Int?
let nutrientName, nutrientNumber, unitName, derivationCode: String
let derivationDescription: String?
let derivationID: Int?
let value: Double?
let foodNutrientSourceID: Int?
let foodNutrientSourceCode, foodNutrientSourceDescription: String?
let rank, indentLevel, foodNutrientID, dataPoints: Int?
enum CodingKeys: String, CodingKey {
case nutrientID = "nutrientId"
case nutrientName, nutrientNumber, unitName, derivationCode, derivationDescription
case derivationID = "derivationId"
case value
case foodNutrientSourceID = "foodNutrientSourceId"
case foodNutrientSourceCode, foodNutrientSourceDescription, rank, indentLevel
case foodNutrientID = "foodNutrientId"
case dataPoints
}
}
为了详细起见,我还会附上API调用本身,以防它与此相关。
class FoodApiSearch: ObservableObject{
@Published var foodDescription = ""
@Published var foodUnit = ""
@Published var calories = ""
//will search for user Input
func searchFood(userItem: String){
//calls api search
guard let url = URL(string: "https://api.nal.usda.gov/fdc/v1/foods/search?api_key=***********?query=\(userItem)") else {return}
URLSession.shared.dataTask(with: url) { (data, _,_) in
let searchResults = try! JSONDecoder().decode(APISearchResults.self, from: data!)
DispatchQueue.main.async {
for item in searchResults.foods{
self.foodDescription = item.lowercaseDescription?.firstCapitalized ?? "food not valid"
self.calories = String(Double(round(item.foodNutrients[3].value!)).removeZerosFromEnd())
}
}
}
.resume()
}
}
发布于 2022-04-15 18:45:08
如果您有未解码的额外变量,则需要包含一个codingKeys
枚举,其中只需要解码所需的JSON。你的可编码应该是:
struct APISearchResults: Codable {
var currentPage, totalPages: Int?
var pageList: [Int]?
//let foodSearchCriteria: FoodSearchCriteria
let foods: [Food]
enum CodingKeys: String, CodingKey {
case foods
}
}
解码器正在寻找不存在于JSON中的currentPage
、totalPages
和pageList
。当您不包括您自己的codingKeys
时,编译器会合成它们,所以在本例中您必须显式地定义它们。
发布于 2022-04-16 08:43:31
基于您显示的json数据,下面的结构模型对我有效。下面是我在测试中使用的代码:
编辑-1:给定提供的“新”json数据,更改了FoodNutrient
struct Food: Codable {
let fdcID: Int
let foodDescription, lowercaseDescription, commonNames, additionalDescriptions: String?
let dataType: String?
let ndbNumber: Int?
let publishedDate, foodCategory, allHighlightFields: String?
let score: Double?
let foodNutrients: [FoodNutrient]? // <-- here optional
let gtinUpc: String? // <-- here not Double
let brandOwner: String?
let ingredients: String?
let marketCountry: String?
let modifiedDate: String?
let dataSource: String?
let servingSize: Double?
let householdServingFullText: String?
enum CodingKeys: String, CodingKey {
case fdcID = "fdcId"
case foodDescription = "description"
case lowercaseDescription, commonNames, additionalDescriptions, dataType, ndbNumber, publishedDate, foodCategory, allHighlightFields, score, gtinUpc, foodNutrients, brandOwner, ingredients, marketCountry, modifiedDate, dataSource, servingSize, householdServingFullText
}
}
struct FoodNutrient: Codable {
let nutrientID: Int?
let nutrientName, nutrientNumber, unitName: String
let value: Double?
let rank, indentLevel, foodNutrientID: Int?
enum CodingKeys: String, CodingKey {
case nutrientID = "nutrientId"
case nutrientName, nutrientNumber, unitName, value, rank, indentLevel
case foodNutrientID = "foodNutrientId"
}
}
struct APISearchResults: Codable {
var currentPage, totalPages: Int? // <-- here
var pageList: [Int]? // <-- here
let foods: [Food]
}
struct ContentView: View {
var body: some View {
Text("testing")
.onAppear {
let json = """
{
"totalHits":396990,
"currentPage":1,
"totalPages":396990,
"pageList":[
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
],
"foodSearchCriteria":{
"dataType":[ ],
"pageNumber":1,
"numberOfResultsPerPage":50,
"pageSize":1,
"requireAllWords":false
},
"foods":[
{
"fdcId":1104067,
"description":"100 GRAND Bar",
"lowercaseDescription":"100 grand bar",
"commonNames":"",
"additionalDescriptions":"$ 100,000 Bar",
"dataType":"Survey (FNDDS)",
"foodCode":91715300,
"publishedDate":"2020-10-30",
"foodCategory":"Candy containing chocolate",
"foodCategoryId":999786,
"allHighlightFields":"",
"score":1.0,
"foodNutrients":[
{
"nutrientId":1003,
"nutrientName":"Protein",
"nutrientNumber":"203",
"unitName":"G",
"value":2.5,
"rank":600,
"indentLevel":1,
"foodNutrientId":13301423
},
{
"nutrientId":1280,
"nutrientName":"PUFA 22:5 n-3 (DPA)",
"nutrientNumber":"631",
"unitName":"G",
"value":0.0,
"rank":15200,
"indentLevel":2,
"foodNutrientId":13301485
},
{
"nutrientId":1292,
"nutrientName":"Fatty acids, total monounsaturated",
"nutrientNumber":"645",
"unitName":"G",
"value":6.04,
"rank":11400,
"indentLevel":1,
"foodNutrientId":13301486
},
{
"nutrientId":1293,
"nutrientName":"Fatty acids, total polyunsaturated",
"nutrientNumber":"646",
"unitName":"G",
"value":1.39,
"rank":12900,
"indentLevel":1,
"foodNutrientId":13301487
}
],
"finalFoodInputFoods":[
{
"foodDescription":"Candies, NESTLE, 100 GRAND Bar",
"gramWeight":100,
"id":102104,
"portionCode":"0",
"portionDescription":"NONE",
"unit":"GM",
"rank":1,
"srCode":19144,
"value":100
}
],
"foodMeasures":[
{
"disseminationText":"1 bar (1.5 oz)",
"gramWeight":43,
"id":246540,
"modifier":"60362",
"rank":1,
"measureUnitAbbreviation":"undetermined",
"measureUnitName":"undetermined",
"measureUnitId":9999
},
{
"disseminationText":"Quantity not specified",
"gramWeight":21,
"id":266827,
"modifier":"90000",
"rank":2,
"measureUnitAbbreviation":"undetermined",
"measureUnitName":"undetermined",
"measureUnitId":9999
}
],
"foodAttributes":[ ],
"foodAttributeTypes":[
{
"name":"Additional Description",
"description":"Additional descriptions for the food.",
"id":1001,
"foodAttributes":[
{
"value":"$ 100,000 Bar",
"id":978293,
"sequenceNumber":1
}
]
},
{
"name":"Attribute",
"description":"Generic attributes",
"id":999,
"foodAttributes":[
{
"value":"5702",
"name":"WWEIA Category number",
"id":991595
},
{
"value":"Candy containing chocolate",
"name":"WWEIA Category description",
"id":999786
}
]
}
],
"foodVersionIds":[ ]
}
]
}
"""
let data = json.data(using: .utf8)!
do {
let searchResults = try JSONDecoder().decode(APISearchResults.self, from: data)
print("\n ---> searchResults:\n \(searchResults) \n")
} catch {
print("\n---> ERROR \(error) \n")
}
}
}
}
注意:“新”json数据是不正确的,结束"aggregations":{ "dataType":
缺少一些部分。
在print(String(data: data!, encoding: .utf8))
之前添加let searchResults = try! JSONDecoder()....
,并向我们展示它真正打印的内容,而不是显示您认为响应给您带来的一些json。那就很容易帮你解决你的解码问题。
https://stackoverflow.com/questions/71887521
复制相似问题