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 codingKeys
enumeració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
, totalPages
y pageList
que 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