我收到以下错误:
无法读取数据,因为它已丢失。
当我运行以下代码时:
struct Indicator: Decodable {
let section: String
let key: Int
let indicator: Int
let threshold: Int
}
var indicators = [Indicator]()
do {
if let file = Bundle.main.url(forResource: "indicators", withExtension: "json") {
indicators = try JSONDecoder().decode([Indicator].self, from: try Data(contentsOf: file))
}
} catch {
print(error.localizedDescription)
}
这些都是一个功能,但为了清楚起见,我删除了它们。我有一个代码块,它在一个不同的文件中非常相似(我从那里复制了这段代码并基本上改了名字)所以我不确定它为什么会发生。 json文件是有效的json,并且正确设置了目标。
由于
答案 0 :(得分:26)
我刚刚解决了类似的问题但是对于属性列表解码器。
这种情况下的错误似乎意味着找不到密钥,而不是整个数据。
尝试在struct可选中设置变量,并且应该在问题所在的位置返回一个nil值。
答案 1 :(得分:22)
尝试打印实际错误而不仅仅是描述。它应该为您提供"No value associated with key someKey (\"actual_key_if_you_defined_your_own\")."
之类的消息,它比localizedDescription
更有用。
答案 2 :(得分:14)
打印error.localizedDescription
会产生误导,因为它仅显示了非常没有意义的通用错误消息。
因此切勿在{{1}}捕获块中使用localizedDescription
。
以简单形式
Decodable
它显示了完整的错误,包括关键信息print(error)
和debugDescription
。context
错误非常全面。
在开发代码时,例如,您可以分别捕获每个Decodable
错误
Decodable
它仅显示最重要的信息。
答案 3 :(得分:2)
刚刚有同样的错误。我在解码器的手动代码中出错。在我的代码属性中,completedOn 是可选的,但我在解码时使用了 try 而不是 try?。当 json 中缺少该值时,该属性的解码将失败。请参阅下面的代码以更好地理解我的意思。
public var uuid: UUID
public var completedOn: Date?
...
required public convenience init(from decoder: Decoder) throws {
self.init()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.uuid = try container.decode(UUID.self, forKey: .uuid)
self.completedOn = try? container.decode(Date.self, forKey: .completedOn)
}
答案 4 :(得分:0)
“由于缺少数据而无法读取数据”
此代码产生的错误:
...catch {
print(error.localizedDescription)
}
原因:似乎密钥丢失或输入错误。
您可以通过以下编码来检查缺少哪个键:
...catch {
debugPrint(error)
}
注意:如果结构键与JSON数据键不同,请参见以下示例: struct中的键是“ title”,而数据中的键是“ name”。
struct Photo: Codable {
var title: String
var size: Size
enum CodingKeys: String, CodingKey
{
case title = "name"
case size
}
}
如果您输错“名称”,则会弹出错误。
此外,如果您错误键入此“ CodingKeys”,则会收到错误消息。
enum CodingKeys:...
答案 5 :(得分:0)
首先将属性设为可选,然后
如果您的情况与此类似,请尝试此 decodeIfPresent
`public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
firstName = try container.decodeIfPresent(String.self, forKey: .firstName)
}`