fonction pour lire un fichier JSON

Bonjour à  tous !


 


J'ai créé une fonction pour lire un fichier JSON. Cette fonction retourne un dictionnaire.


 


J'aimerai savoir si ma fonction est correcte, surtout vis-à -vis de la gestion des erreurs.


Pouvez-vous me dire ce que vous en pensez ?


Je vous remercie !



func readJSON(JSONData: nameFile) -> DataFiles {
do {
if let file = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let path = file.appendingPathComponent(JSONData.rawValue)
let data = try Data(contentsOf: path)
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let object = json as? DataFiles {
return object
} else {
print("JSON is invalid")
return ["error": "type"] as DataFiles
}
} else {
print("no file")
return ["error": "no file"] as DataFiles
}
} catch {
let errorCatched = error.localizedDescription
print(errorCatched)
return ["error": "\(errorCatched)"] as DataFiles
}
}

Réponses

  • Je ne parle pas Swift, mais ton code capte les 2 tryData(contentsOf:)JSONSerialization.jsonObject(with:options:) ?

  • CéroceCéroce Membre, Modérateur
    novembre 2017 modifié #3

    1) Pourquoi, en cas d'erreur, veux-tu renvoyer un JSON à  la place du DataFiles ?!


    2) Préfère NSLog() à  print() pour que les erreurs apparaissent dans les logs de l'iPhone.


    3) repose-toi plutôt justement sur les exceptions pour renvoyer tes propres erreurs:


    https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/ErrorHandling.html


    (Il faudrait marquer ta fonction 'throws', qu'elle jette ses propres erreurs, et donc les capturer avec le do {} catch plus haut.)


    4) le mot-clé 'guard' améliorerait la lisibilité


  • Je vous remercie !


     


    Larme, les deux try dont tu parles sont bien présents : respectivement c'est let data et let json.


     


    Céroce, je vais répondre à  tout tes points.


     


    1) Je ne comprend pas cette première remarque... Je renvoie toujours le DataFiles, car la fonction retourne un DataFiles. Donc, je n'ai pas trop le choix...


    2) Merci pour NSlog(), c'est noté !


    3) Merci pour le lien. Je dois avouer que je n'ai pas bien saisi l'utilité de 'throws', mais je vais me renseigner !


    4) Il vaut mieux utiliser guard que if. C'est noté aussi !


     


    Je reposterai la fonction modifiée. Je vous remercie beaucoup !


  • Me revoilà  !


     


    J'ai refait ma fonction, et j'ai du réécrire les appels de la fonction.



    func readJSON(JSONData: nameFile) throws -> DataFiles {
    do {
    guard let file = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { throw JSONError.noData }
    let path = file.appendingPathComponent(JSONData.rawValue)
    let data = try Data(contentsOf: path)
    let json = try JSONSerialization.jsonObject(with: data, options: [])
    guard let object = json as? DataFiles else { throw JSONError.invalid }
    return object
    } catch {
    let errorCatched = error.localizedDescription
    NSLog(errorCatched)
    return ["error": "\(errorCatched)"] as DataFiles
    }
    }

    Et voici un appel de ladite fonction :



    do {
    commentSaved = try filesManager.readJSON(JSONData: .opinionsSaved)
    } catch {
    NSLog(FilesManager.JSONError.invalid.errorDescription!)
    NSLog(FilesManager.JSONError.noData.errorDescription!)
    }
  • CéroceCéroce Membre, Modérateur
    novembre 2017 modifié #6

    1) Je ne comprends pas cette première remarque... Je renvoie toujours le DataFiles, car la fonction retourne un DataFiles. Donc, je n'ai pas trop le choix...




    Quand tu écris 



    return ["error": "\(errorCatched)"]

    tu renvoies un dictionnaire, pas un DataFiles. D'ailleurs, c'est pour cela que tu es obligé d'écrire 'as DataFiles'. ça semble une erreur de ta part.

     



    3) Merci pour le lien. Je dois avouer que je n'ai pas bien saisi l'utilité de 'throws', mais je vais me renseigner !



    L'instruction 'throw' lance une exception.

    L'annotation 'throws' indique que la méthode peut lancer des exceptions. Les méthodes qui font appel à  cette méthode devront utiliser 'try' et soit attraper les exceptions à  l'aide do... catch, soit les relancer.


    Dans ton exemple de méthode, il ne devrait pas y avoir de do...catch. Les exceptions devraient être attrapées par la méthode appelante.


  • Luc-ALuc-A Membre
    novembre 2017 modifié #7

    Céroce, je te remercie pour tes explications !


     


    Effectivement, pour le DataFiles, c'est une erreur de ma part. J'ai bêtement suivi l'auto correction.


     


    Pour compléter les informations sur mon code :



    typealias DataFiles = [String:Any]

    Cela me permet de gérer plus facilement les données écrites et récupérées dans les fichiers JSON.


     


    Je comprend mieux à  quoi sert "throw" et "throws".


     


    J'ai revu le code. Ma méthode n'a plus de do ... catch :



    func readJSON<T>(JSONData: nameFile) throws -> T {
    guard let file = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { throw JSONError.noData }
    let path = file.appendingPathComponent(JSONData.rawValue)
    let data = try Data(contentsOf: path)
    let json = try JSONSerialization.jsonObject(with: data, options: [])
    guard let object = json as? T else { throw JSONError.invalid }
    return object
    }

    Il me reste à  revoir l'appel de la fonction.



    do {
    commentSaved = try filesManager.testJSON(JSONData: .opinionsSaved)
    } catch {
    NSLog(error.localizedDescription)
    }

    Est-ce mieux comme ça ??


  • Bonjour !


     


    Pour être sur, est ce que le code suivant suffit pour récupérer toutes les erreurs ?



    NSLog(error.localizedDescription)

    Je vous remercie !


Connectez-vous ou Inscrivez-vous pour répondre.