web-dev-qa-db-fra.com

Lire un fichier JSON avec Swift 3

J'ai un fichier JSON appelé points.json , et une fonction de lecture comme:

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)
}

Cela ne fonctionne pas, aucune aide?

32
Xie

Votre problème ici est que vous forcez le déroulé des valeurs et en cas d'erreur, vous ne pouvez pas savoir d'où ça vient. 

Au lieu de cela, vous devez gérer les erreurs et décompresser vos options en toute sécurité.

Et comme @vadian note à juste titre dans son commentaire, vous devriez utiliser 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)
    }
}

Lorsque vous codez dans Swift, ! est généralement une odeur de code. Bien sûr, il existe des exceptions (IBOutlets et autres), mais essayez de ne pas utiliser la décompression forcée avec ! vous-même et décompressez-la toujours en toute sécurité.

94
ayaio

Le code Swift 4.2/iOS 12 ci-dessous montre une possible réécriture de votre méthode, qui évite de forcer l'extraction des valeurs facultatives et gère en douceur les erreurs potentielles:

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)")
    }
}
1
Imanou Petit