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

Jal*_*lem 27 json ios swift

我收到以下错误:

由于缺少数据,因此无法读取数据.

当我运行以下代码时:

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)
    }
Run Code Online (Sandbox Code Playgroud)

这些都是功能,但为了清楚起见,我删除了它们.我有一个代码块,它在一个不同的文件中非常相似(我从那里复制了这些代码并且基本上改变了名称)所以我不确定它为什么会发生.json文件是有效的json并且正确设置了它的目标.

谢谢

小智 39

我刚刚解决了类似的问题,但是对于属性列表解码器.

这种情况下的错误似乎意味着找不到密钥而不是整个数据.

尝试使结构中的变量可选,它应该返回问题所在的nil值.

  • print(response.error as Any) 这将为您提供有关根据此答案需要处理的键的全面信息。 (4认同)

vad*_*ian 36

打印error.localizedDescription具有误导性,因为它只显示一个非常无意义的通用错误消息.

所以,千万不要用localizedDescriptionDecodablecatch块.

只是简单的形式

print(error)
Run Code Online (Sandbox Code Playgroud)

它显示了完整的错误,包括关键信息debugDescriptioncontext.Decodable错误非常全面.


在开发代码时,您可以分别捕获每个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)
}
Run Code Online (Sandbox Code Playgroud)

它仅显示最重要的信息.

  • 圣!你刚刚拯救了我的 azz。6 个小时我没有得到任何 json 数据。没有错误,没有警告,什么都没有。我的表根本没有加载数据。然后我删除了 `localizedDescription` 并尝试了 `error`。它告诉我 3 个不匹配的位置。这不是因为拼写,而是因为我在模型中具有 json 中不存在的额外属性。加上另一个 Bool json 问题。我无法相信`localizedDescription` 如此糟糕。他们应该禁止 Swift 这样做。谢谢瓦迪安!!!!!!!!! (2认同)
  • 我现在知道了。然而我受到了创伤,我再也不会在我的生活中使用 localizedDescription 了。绝不!;( (2认同)

小智 24

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

  • 请注意,如果您尝试在控制台中执行 `po` 并且它不起作用,则可能需要在代码中使用显式的 `print` 语句。 (2认同)

Fua*_*mad 14

“无法读取数据,因为它丢失了”

来自此代码的错误:

...catch {
    print(error.localizedDescription)
}
Run Code Online (Sandbox Code Playgroud)

因为:似乎密钥丢失或输入错误。

您可以通过如下编码来检查缺少哪个键

...catch {
    debugPrint(error)
}
Run Code Online (Sandbox Code Playgroud)

注意:如果 struct 键与 JSON 数据键不同,请参见下面的示例:struct 中的键是“title”,而 data 中的键是“name”。

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

    enum CodingKeys: String, CodingKey
    {
        case title = "name"
        case size
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你输入错误'name',错误会弹出。

此外,如果您输入错误此“CodingKeys”,您将收到错误消息。

enum CodingKeys:...
Run Code Online (Sandbox Code Playgroud)


小智 7

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

print(error.localizedDescription) 
Run Code Online (Sandbox Code Playgroud)

因为它在涉及 JSON 文件时极具误导性。相反,只需使用

print(error)
Run Code Online (Sandbox Code Playgroud)


Rai*_*kas 5

刚刚有同样的错误。我在解码器的手动代码中遇到错误。在我的代码中,属性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)
}
Run Code Online (Sandbox Code Playgroud)