【问题标题】:valueNotFound Error when getting back an API call into JSON将 API 调用返回到 JSON 时出现 valueNotFound 错误
【发布时间】:2021-05-07 12:09:13
【问题描述】:

当我进行 API 调用并取回数据时,它无法正确解码到我的结构中。

我得到的错误是:

无法转换 valueNotFound(Swift.Int, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys( stringValue: "newDeathsByDeathDate", intValue: nil)], debugDescription: "预期的 Int 值,但发现为 null。",underlyingError: nil))

我的代码是:

override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = """
https://api.coronavirus.data.gov.uk/v1/data?filters=areaType=nation;areaName=england&structure=%7b%22date%22:%22date%22,%22areaName%22:%22areaName%22,%22areaCode%22:%22areaCode%22,%22newCasesByPublishDate%22:%22newCasesByPublishDate%22,%22cumCasesByPublishDate%22:%22cumCasesByPublishDate%22,%22newDeathsByDeathDate%22:%22newDeathsByDeathDate%22,%22cumDeathsByDeathDate%22:%22cumDeathsByDeathDate%22%7d
"""
        print(url)
        print(NSURL(string: url))
        getData(from: url)
        
        // Do any additional setup after loading the view.
    }
    
    private func getData(from url: String) {
        guard let theURL = URL(string: url) else { print ("oops"); return }
        let getfromurl = URLSession.shared.dataTask(with: theURL, completionHandler: {data, response, error in
            guard let data = data, error == nil else{
                print("Something Went Wrong")
                return
            }
            
            //Have data
            var result: Response?
            do {
                result = try JSONDecoder().decode(Response.self, from: data)
            }
            catch{
                print("failed to convert \(error)")
            }
            
            guard let json = result else {
                return
            }
            
            print(json.data)
        })
        getfromurl.resume()
    
    }
    
    
}

我的结构是:

struct Response: Codable {
    let data: [MyData]
}

struct MyData: Codable{
    let date: String
    let areaName: String
    let areaCode: String
    let newCasesByPublishDate: Int
    let cumCasesByPublishDate: Int
    let newDeathsByDeathDate: Int
    let cumDeathsByDeathDate: Int
}

【问题讨论】:

  • 显然在你的结构中 newDeathsByDeathDateInt 而不是 Int? 所以在解码 json 时它期望键 newDeathsByDeathDate 的 Int 值但它发现 nil 并且因为你的声明说它需要有一个 Int 值它失败了。我不确定有多少响应与您的结构匹配,您是否完全确定 json 中的所有键都正确匹配结构中的键?这是实际的层次结构吗?你确定它需要返回 Int 而不是 Int 吗?或 String 或 double 或其他什么?如果您需要自定义映射,您可能需要覆盖 init(from decoder:

标签: ios json swift


【解决方案1】:

请仔细查看JSON,键newDeathsByDeathDatecumDeathsByDeathDate的值可以是null

使相应结构成员的类型可选

struct MyData: Codable{
    let date: String
    let areaName: String
    let areaCode: String
    let newCasesByPublishDate: Int
    let cumCasesByPublishDate: Int?
    let newDeathsByDeathDate: Int?
    let cumDeathsByDeathDate: Int?
}

或者 - 保留非可选值 - 手动解码 JSON 并将值设置为 0,如果它们是 null


struct MyData : Decodable {
    let date, areaName, areaCode: String
    let newCasesByPublishDate, cumCasesByPublishDate : Int
    let newDeathsByDeathDate, cumDeathsByDeathDate: Int
    
    private enum CodingKeys : String, CodingKey { case date, areaName, areaCode, newCasesByPublishDate, cumCasesByPublishDate, newDeathsByDeathDate, cumDeathsByDeathDate }
    
    init(from decoder : Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        date = try container.decode(String.self, forKey: .date)
        areaName = try container.decode(String.self, forKey: .areaName)
        areaCode = try container.decode(String.self, forKey: .areaCode)
        newCasesByPublishDate = (try? container.decode(Int.self, forKey: .newCasesByPublishDate)) ?? 0
        cumCasesByPublishDate = (try? container.decode(Int.self, forKey: .cumCasesByPublishDate)) ?? 0
        newDeathsByDeathDate = (try? container.decode(Int.self, forKey: .newDeathsByDeathDate)) ?? 0
        cumDeathsByDeathDate = (try? container.decode(Int.self, forKey: .cumDeathsByDeathDate)) ?? 0
    }
}

同样,不要通过打印无意义的内容来忽略有用的错误消息

替换

print("Something Went Wrong")

print("An error occured:", error!)

【讨论】:

  • 是的,我确实看到了,并且已经更改了,但仍然出现错误。
  • 只需将所有内容设为可选,因为似乎所有内容都可能丢失。或者使用像 stackoverflow.com/questions/44603248 这样的字典方法(参见 Vasily 的回答)
  • cumCasesByPublishDate 也可以为空,请参阅编辑。
猜你喜欢
  • 2019-05-01
  • 1970-01-01
  • 2016-03-25
  • 1970-01-01
  • 2023-03-23
  • 2017-03-06
  • 1970-01-01
  • 2021-10-30
  • 2017-10-01
相关资源
最近更新 更多