Estoy decodificando una respuesta JSON en mi aplicación Swift, y el código decidió no funcionar cuando cambié la URL de API.
Esta es mi respuesta json
{
"foodSearchCriteria":{
"query":"eggs",
"generalSearchInput":"eggs",
"pageNumber":1,
"numberOfResultsPerPage":50,
"pageSize":50,
"requireAllWords":false
},
"foods":[
{
"fdcId":577532,
"description":"EGGS",
"lowercaseDescription":"eggs",
"dataType":"Branded",
"gtinUpc":"021130049134",
"publishedDate":"2019-04-01",
"brandOwner":"Safeway, Inc.",
"ingredients":"",
"marketCountry":"United States",
"foodCategory":"Eggs & Egg Substitutes",
"modifiedDate":"2017-07-14",
"dataSource":"LI",
"servingSizeUnit":"g",
"servingSize":44.0,
"householdServingFullText":"1 EGG",
"allHighlightFields":"",
"score":848.0136,
}
Me encuentro con este error.
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))
Supuse que era porque no estaba haciendo coincidir mi var de "alimentos" correctamente, pero no aparece de esa manera. A continuación, adjunté fragmentos de mi llamada y estructuras.
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
}
}
Para fines de detalle, también adjuntaré la llamada API en sí misma en caso de que esté relacionada con eso.
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()
}
}
Solución del problema
Si tiene variables adicionales que no están decodificadas, debe incluir una codingKeysenumeración con solo el JSON que necesita decodificar. Su Codificable debe ser:
struct APISearchResults: Codable {
var currentPage, totalPages: Int?
var pageList: [Int]?
//let foodSearchCriteria: FoodSearchCriteria
let foods: [Food]
enum CodingKeys: String, CodingKey {
case foods
}
}
El decodificador está buscando currentPage, totalPagesy pageListque no existen en el JSON. Cuando no incluye su propio codingKeys, el compilador los sintetiza, por lo que debe definirlos explícitamente en este caso.
No hay comentarios:
Publicar un comentario