在Swift中解码JSON时出现“数据无法读取,因为它丢失了”错误

5uzkadbs  于 2023-04-04  发布在  Swift
关注(0)|答案(7)|浏览(309)

我收到以下错误:
无法读取数据,因为数据丢失。
当我运行下面的代码时:

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,并且正确设置了它的目标。
谢谢

ztmd8pv5

ztmd8pv51#

打印error.localizedDescription具有误导性,因为它只显示一个毫无意义的一般错误消息。
所以永远不要在Decodable catch块中使用localizedDescription
简单的形式就是

print(error)

它显示了完整的错误,包括关键信息debugDescriptioncontextDecodable错误非常全面。
在开发代码时,您可以分别捕获每个Decodable错误,例如

} catch let DecodingError.dataCorrupted(context) {
    print(context)
} catch let DecodingError.keyNotFound(key, context) {
    print("Key '\(key)' not found:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch let DecodingError.valueNotFound(value, context) {
    print("Value '\(value)' not found:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch let DecodingError.typeMismatch(type, context)  {
    print("Type '\(type)' mismatch:", context.debugDescription)
    print("codingPath:", context.codingPath)
} catch {
    print("error: ", error)
}

它只显示最重要的信息。

sirbozc5

sirbozc52#

我刚刚解决了一个类似的问题,但对我的结束属性列表解码器。
这种情况下的错误似乎意味着没有找到键,而不是整个数据。

尝试将结构体中的变量设置为可选,它应该返回一个nil值,这就是问题所在。

efzxgjgh

efzxgjgh3#

“数据丢失,无法读取”

来自此代码的错误:

...catch {
    print(error.localizedDescription)
}

因为:似乎缺少一个键或键入错误。
您可以通过以下代码检查缺少哪个键

...catch {
    debugPrint(error)
}

注意:如果结构键与JSON数据键不同,请参见以下示例:结构中的键是'title',但数据中的键是'name'。

struct Photo: Codable {
    var title: String
    var size: Size

    enum CodingKeys: String, CodingKey
    {
        case title = "name"
        case size
    }
}

如果您输入错误的“名称”,错误将弹出。
此外,如果您输入错误的'CodingKeys',您将得到错误。

enum CodingKeys:...
zysjyyx4

zysjyyx44#

尝试打印实际的错误而不仅仅是描述。它应该给予你一个像"No value associated with key someKey (\"actual_key_if_you_defined_your_own\")."这样的消息,这比localizedDescription有用得多。

um6iljoc

um6iljoc5#

刚刚有一个同样的错误。我在解码器的手动代码中有一个错误。在我的代码中,属性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)
}
t3psigkw

t3psigkw6#

大多数人使用但不应该使用的东西是

print(error.localizedDescription)

因为当涉及到JSON文件时,它是非常误导的。

print(error)
b4lqfgs4

b4lqfgs47#

首先将属性设置为可选,然后
如果您的情况类似于此,请尝试此decodeIfPresent

`public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    firstName = try container.decodeIfPresent(String.self, forKey: .firstName)
    }`

相关问题