2017-09-23 5 views
2

J'essaie de comprendre pourquoi l'utilisation d'URL optionnelles provoque l'échec de mon décodage JSON avec Swift 4. J'ai déjà versé sur la vidéo WWDC "Quoi de neuf dans Foundation", Apples Playground exemples, et un tas de lieux sur Internet, mais n'ont pas trouvé une solution.URL optionnelles entraînant l'échec du décodage JSON dans Swift 4

Ceci est un test que j'ai créé pour montrer le problème. Dites ceci est mes données JSON:

let json = """ 
{ 
    "kind" : "", 
    "total" : 2, 
    "image_url" : "https://www.myawesomeimageURL.com/awesomeImage.jpg" 
} 
""".data(using: .utf8)! 

Et voici ma struct:

struct BusinessService: Decodable { 
    let kind: String? 
    let total: Int 
    let image_url : URL? 
} 

Et voici où je sérialiser:

let myBusiness = try? JSONDecoder().decode(BusinessService.self, from: json) 
print(myBusiness) 

Maintenant, le problème est de savoir si je reçois JSON data où image_url est manquant, le décodage json échoue et me donne zéro. Je suis confus quant à pourquoi "kind" peut être une chaîne optionnelle et ne pas faire échouer le décodage json quand il n'a pas de valeur, mais image_url ne peut pas être une URL optionnelle sans provoquer l'échec de json.

J'ai essayé de comprendre cela pendant deux jours maintenant sans aucune chance. Quelqu'un at-il un aperçu de la raison pour laquelle cela échouerait?

J'ai remarqué une pièce supplémentaire du puzzle, et l'image_url dans le json n'a pas vraiment besoin d'être une URL d'image valide. Je peux saisir n'importe quelle chaîne et ma structure est sérialisée, donc je pense que je ne comprends pas comment cela fonctionne. Je pensais que l'URL ne serait automatiquement remplie que si elle pouvait être convertie en URL valide, ce qui n'est pas le cas.

Toute idée à ce sujet serait grandement appréciée.

Répondre

2

Cela fonctionne pour moi comme prévu. Réglage image_url à null ou de le laisser sortir conduit complètement à un BusinessService valide se décodée avec une valeur nil pour le champ image_url:

struct Example: Decodable { 
    let url: URL? 
} 

// URL is present. This works, obviously. 
try JSONDecoder().decode(Example.self, from: """ 
    { "url": "foo" } 
    """.data(using: .utf8)!) 

// URL is missing, indicated by null. Also works. 
try JSONDecoder().decode(Example.self, from: """ 
    { "url": null } 
    """.data(using: .utf8)!) 

// URL is missing, not even the key is present. Also works. 
try JSONDecoder().decode(Example.self, from: """ 
    {} 
    """.data(using: .utf8)!) // works, too 

Le seul problème vient quand je fournir une valeur d'URL non valide, comme une chaîne vide pour le champ. Donc je suppose que c'est ton problème?

// This throws: "Invalid URL string." 
try JSONDecoder().decode(Example.self, from: """ 
    { "url": "" } 
    """.data(using: .utf8)!) 

Vous devez envoyer une valeur « none » pour le champ URL en envoyant null ou sortant de la ligne entière, non pas envoyer une chaîne vide.

Je suis confus quant à la raison pour laquelle « genre » peut être une chaîne facultative et ne pas provoquer le décodage JSON à l'échec quand il n'a pas de valeur, mais image_url ne peut pas être une URL en option sans provoquer JSON échec.

La différence est que "" dans JSON est une valeur String valide, mais pas une URL valide.

+0

Merci beaucoup pour l'explication. Cela me rendait fou toute la fin de semaine. Je ne travaille pas beaucoup avec JSON, donc je n'ai pas réalisé que null était une valeur valide. Il est dommage que l'API que j'utilise (Yelp) passe "" au lieu de null. Je vais devoir regarder dans les conteneurs JSON (je pense) pour résoudre ce problème. Merci pour votre aide! – SN81

+0

Heureux de vous aider!Les cas "vides" sont toujours un peu compliqués, car il est facile de confondre une chaîne vide et une chaîne manquante. Le type 'Optional' dans Swift rend cela un peu meilleur, car vous obtenez' .none' quand la chaîne est manquante et '.some (" ")' quand la chaîne est présente, mais vide. Passer '' "' 'pour les URL manquantes est un mauvais choix, en effet. – zoul