使用Swift 3读取JSON文件

39

我有一个名为points.json的JSON文件,以及一个读取函数:

private func readJson() {
    let file = Bundle.main.path(forResource: "points", ofType: "json")
    let data = try? Data(contentsOf: URL(fileURLWithPath: file!))
    let jsonData = try? JSONSerialization.jsonObject(with: data!, options: []) as! [String:Any]
    print(jsonData)
}

它不起作用,需要帮助吗?


1
什么不起作用?添加一个 do-catch 块以获取错误信息。顺便说一下,Bundle 已经有了与 URL 相关的 API 来检索资源。 - vadian
2个回答

107

你的问题在于强制解包数值,在出现错误时无法确定错误来源。

相反,你应该处理错误并安全地解包可选项。

正如 @vadian 在他的评论中所指出的那样,你应该使用 Bundle.main.url

private func readJson() {
    do {
        if let file = Bundle.main.url(forResource: "points", withExtension: "json") {
            let data = try Data(contentsOf: file)
            let json = try JSONSerialization.jsonObject(with: data, options: [])
            if let object = json as? [String: Any] {
                // json is a dictionary
                print(object)
            } else if let object = json as? [Any] {
                // json is an array
                print(object)
            } else {
                print("JSON is invalid")
            }
        } else {
            print("no file")
        }
    } catch {
        print(error.localizedDescription)
    }
}

在使用Swift编程时,通常情况下,!被视为代码异味。当然也有例外情况(如IBOutlets和其他情况),但是尽量避免自己使用强制解包操作符!,而是始终使用安全解包。


谢谢!它打印了“无法读取数据,因为它不是正确的格式。” - Xie
1
所以我认为问题出在JSON文件上。 - Xie
2
是的,这就是catch捕获了来自JSONSerialization的错误。你的JSON文件很可能是无效的。请注意:始终处理错误。 :) - Eric Aya
5
通常情况下,使用叹号 ! 是一种代码坏味道...请尽量避免使用强制解包操作 !,并始终使用安全解包操作。+1 - MANN
我不完全同意你关于“在编写Swift代码时,通常情况下,!是一种代码异味”的说法。当然有例外情况(如IBOutlets和其他情况),但是当你保证变量下存储了值时,使用Swift强制解包是可以的。造成代码异味的是你的设计而不是语言本身。因此,我们应该根据实际情况谨慎使用强制解包,而不是一概而论地认为它是一种代码异味。 - Parama Dharmika
1
@ParamaDharmika 代码异味意味着代码存在问题,而不是语言。你误解了我的话。我同意你的结论,我们实际上在思考同样的事情... 我说的是代码(所写的内容),而不是用于编写它的语言。 - Eric Aya

5
下面是Swift 5 / iOS 12.3的示例代码,展示了一种可能的重写方法,避免了对可选值进行强制解包,并且在处理潜在错误时更加友好:
import Foundation

func readJson() {
    // Get url for file
    guard let fileUrl = Bundle.main.url(forResource: "Data", withExtension: "json") else {
        print("File could not be located at the given url")
        return
    }

    do {
        // Get data from file
        let data = try Data(contentsOf: fileUrl)

        // Decode data to a Dictionary<String, Any> object
        guard let dictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
            print("Could not cast JSON content as a Dictionary<String, Any>")
            return
        }

        // Print result
        print(dictionary)
    } catch {
        // Print error if something went wrong
        print("Error: \(error)")
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接