【问题标题】:Swift 4 Decodable - No value associated with key CodingKeys [duplicate]Swift 4 Decodable - 没有与键 CodingKeys 关联的值 [重复]
【发布时间】:2019-08-28 22:38:18
【问题描述】:

我正在我的 Swift 应用程序中解码 JSON 响应,并且代码在它决定停止工作之前一直有效。

这是我的 json 回复

{
    "foods": [
        {
            "food_name": "Milk Chocolate",
            "brand_name": "Snickers",
            "serving_weight_grams": 41.7,
            "nf_calories": 212.3,
            "nf_total_fat": 11.6,
            "nf_saturated_fat": 4,
            "nf_total_carbohydrate": 22.7,
            "nf_protein": 3.9
        }
    ]
}

这是解码我的 json 的代码

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        guard let data = data else { return }
        
        print(String(data: data, encoding: .utf8)!)
        do {
            //Decode dataResponse received from a network request
            let decoder = JSONDecoder()
            let foods = try decoder.decode(JSONFoods.self, from: data) //Decode JSON Response Data
            
            self.jsonfood = foods.JSONFood[0]
            print(self.jsonfood!)
            
        } catch let parsingError {
            print("Error", parsingError)
        }
        
    }
    task.resume()

我的结构是

struct JSONFoods: Decodable {
var JSONFood: [JSONFood]    
}

struct JSONFood: Decodable{
var food_name: String
var brand_name: String
var nf_calories: Int
var nf_protein: Int
var nf_total_fat: Int
var nf_total_carbohydrate: Int
var serving_weight_grams: Int
}

我得到的错误信息是这样的

keyNotFound(CodingKeys(stringValue: "JSONFood", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "没有与键 CodingKeys 关联的值(stringValue: "JSONFood", intValue: nil) ( "JSONFood").", 底层错误:nil))

如果我将 decode(JSONFoods.self, from: data) 替换为 decode(JSONFood.self, from: data) 我收到此错误消息

keyNotFound(CodingKeys(stringValue: "food_name", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "没有与键 CodingKeys 关联的值(stringValue: "food_name", intValue: nil) ( "food_name").", 基础错误:nil))

我到处搜索都没有运气,非常感谢任何帮助

【问题讨论】:

  • JSONFood != foods.

标签: json swift decodable


【解决方案1】:

你需要

struct Root: Codable {
    let foods: [Food]
}

struct Food: Codable {
    let foodName: String?
    let  brandName: String
    let servingWeightGrams, nfCalories, nfTotalFat: Double
    let nfSaturatedFat: Int
    let nfTotalCarbohydrate, nfProtein: Double

    enum CodingKeys: String, CodingKey {
        case foodName = "food_name"
        case brandName = "brand_name"
        case servingWeightGrams = "serving_weight_grams"
        case nfCalories = "nf_calories"
        case nfTotalFat = "nf_total_fat"
        case nfSaturatedFat = "nf_saturated_fat"
        case nfTotalCarbohydrate = "nf_total_carbohydrate"
        case nfProtein = "nf_protein"
    }
}

首先:你应该是JSONFood,而它应该是foods

第二个:food_name 在当前的 json 根目录中不存在,所以这会失败

let foods = try decoder.decode(JSONFoods.self, from: data) //Decode JSON Response Data

万一利用convertFromSnakeCase

let str = """

{"foods":[{"food_name":"Milk Chocolate","brand_name":"Snickers","serving_weight_grams":41.7,"nf_calories":212.3,"nf_total_fat":11.6,"nf_saturated_fat":4,"nf_total_carbohydrate":22.7,"nf_protein":3.9}]}

"""

    do {
        let res = JSONDecoder()
        res.keyDecodingStrategy = .convertFromSnakeCase
        let ss = try res.decode(Root.self, from:Data(str.utf8))
        print(ss)
    }
    catch {
        print(error)
    }

struct Root: Codable {
    let foods: [Food]
}

struct Food: Codable {
    let foodName: String?
    let  brandName: String
    let servingWeightGrams, nfCalories, nfTotalFat: Double
    let nfSaturatedFat: Int
    let nfTotalCarbohydrate, nfProtein: Double
}

【讨论】:

  • 不需要将JSONFoods结构重命名为Root
  • 我会这样做,以防有多个结构用于突出显示基本模型
  • 出现问题中的第二个错误是因为 OP 将子结构 JSONFood 解码为根对象。 food_name 可能丢失与此无关。为什么不建议.convertFromSnakeCase 策略来摆脱CodingKeys
  • 我只是在评论之前编辑它:),是的,我同意蛇案例更好,但动态站点生成现在可能不会考虑它=D
猜你喜欢
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
相关资源
最近更新 更多