J'essaie d'utiliser JSONDecoder pour convertir un fichier JSON en structures dans Swift. J'ai donc écrit toutes les structures, les ai révisées pendant des heures et cette erreur persiste. Je ne sais pas s'il y a un moyen de voir la ligne qui donne ceci. Je posterai ma structure ci-dessous et les liens du fichier Json juste après.
La description complète de l'erreur est la suivante:
typeMismatch (Swift.Dictionary <Swift.String, Any>, Swift.DecodingError.Context (codingPath: [], debugDescription: "Devrait décoder le dictionnaire <String, Any> mais a trouvé un tableau à la place.",
// Created by Breno Ramos on 28/12/17.
// Copyright © 2017 brenor2. All rights reserved.
//
import Foundation
struct Owner:Decodable {
let login : String?
let id : Double?
let avatar_url : String?
let gravatar_id : String?
let url : String?
let html_url : String?
let followers_url : String?
let following_url : String?
let gists_url : String?
let starred_url : String?
let subscriptions_url : String?
let organizations_url : String?
let repos_url : String?
let events_url : String?
let received_events_url : String?
let type : String?
let site_admin : Bool?
}
struct License:Decodable {
let key : String?
let name : String?
let spdx_id : String?
let url : String?
}
struct Repo:Decodable {
let id : Double?
let name : String?
let full_name : String?
let owner : Owner?
let `private` : Bool?
let html_url : String?
let description : String?
let fork : Bool?
let url : String?
let forks_url : String?
let keys_url : String?
let collaborators_url : String?
let teams_url : String?
let hooks_url : String?
let issue_events_url : String?
let events_url : String?
let assignees_url : String?
let branches_url : String?
let tags_url : String?
let blobs_url : String?
let git_tags_url : String?
let git_refs_url : String?
let trees_url : String?
let statuses_url : String?
let languages_url : String?
let stargazers_url : String?
let contributors_url : String?
let subscribers_url : String?
let subscription_url : String?
let commits_url : String?
let git_commits_url : String?
let comments_url : String?
let issue_comment_url : String?
let contents_url : String?
let compare_url : String?
let merges_url : String?
let archive_url : String?
let downloads_url : String?
let issues_url : String?
let pulls_url : String?
let milestones_url : String?
let notifications_url : String?
let labels_url : String?
let releases_url : String?
let deployments_url : String?
let created_at : String?
let updated_at : String?
let pushed_at : String?
let git_url : String?
let ssh_url : String?
let clone_url : String?
let svn_url : String?
let homepage : String?
let size : Double?
let stargazers_count : Double?
let watchers_count : Double?
let language : String?
let has_issues : Bool?
let has_projects : Bool?
let has_downloads : Bool?
let has_wiki : Bool?
let has_pages : Bool?
let forks_count : Double?
let mirror_url : String?
let archived : Bool?
let open_issues_count : Double?
let license : License?
let forks : Double?
let open_issues : Double?
let topics : Topic?
let permissions : Permissions?
let watchers : Double?
let default_branch : String?
// let score : Double?
// let subscribers_count : Double?
// let network_count : Double?
// let allow_rebase_merge: Bool?
// let allow_squash_merge: Bool?
// let allow_merge_commit: Bool?
}
struct Topic:Decodable {
let topics : [String]?
}
struct Permissions:Decodable {
let admin : Bool
let Push : Bool
let pull : Bool
}
struct RepoList:Decodable{
let total_count : Int?
let incomplete_results : Bool?
let items : [Repo]?
}
struct User:Decodable {
let login: String?
let id: Double?
let avatar_url: String?
let gravatar_id: String?
let url: String?
let html_url: String?
let followers_url: String?
let following_url: String?
let gists_url: String?
let starred_url: String?
let subscriptions_url: String?
let organizations_url: String?
let repos_url: String?
let events_url: String?
let received_events_url: String?
let type: String?
let site_admin: Bool?
}
struct Creator:Decodable {
let login: String?
let id: Double?
let avatar_url: String?
let gravatar_id: String?
let url: String?
let html_url: String?
let followers_url: String?
let following_url: String?
let gists_url: String?
let starred_url: String?
let subscriptions_url: String?
let organizations_url: String?
let repos_url: String?
let events_url: String?
let received_events_url: String?
let type: String?
let site_admin: Bool?
}
struct Link:Decodable {
let href :String?
}
struct _Links:Decodable {
let `self` :Link?
let html :Link?
let issue :Link?
let comments :Link?
let review_comments :Link?
let review_comment :Link?
let commits :Link?
let statuses :Link?
}
struct Base:Decodable {
let label :String?
let ref :String?
let sha :String?
let user :User?
let repo :Repo?
}
struct Head:Decodable {
let label :String?
let ref :String?
let sha :String?
let user :User?
let repo :Repo?
}
struct Milestone:Decodable {
let url:String?
let html_url:String?
let labels_url:String?
let id: Double?
let number:Double?
let title:String?
let description:String?
let creator:Creator?
let open_issues:Double?
let closed_issues:Double?
let state:String?
let created_at:String?
let updated_at:String?
let closed_at:String?
let due_on:String?
}
struct Assignee:Decodable {
let login :String?
let id :Double?
let avatar_url :String?
let gravatar_id :String?
let url :String?
let html_url :String?
let followers_url :String?
let following_url :String?
let gists_url :String?
let starred_url :String?
let subscriptions_url :String?
let organizations_url :String?
let repos_url :String?
let events_url :String?
let received_events_url :String?
let type :String?
let site_admin :Bool?
}
struct Reviewers:Decodable {
let login: String?
let id: Double?
let avatar_url: String?
let gravatar_id: String?
let url: String?
let html_url: String?
let followers_url: String?
let following_url: String?
let gists_url: String?
let starred_url: String?
let subscriptions_url: String?
let organizations_url: String?
let repos_url: String?
let events_url: String?
let received_events_url: String?
let type: String?
let site_admin: Bool?
}
struct Pull:Decodable {
let id: Double?
let url:String?
let html_url:String?
let diff_url:String?
let patch_url:String?
let issue_url:String?
let number:Double?
let state:String?
let locked:Bool?
let title:String?
let user:User?
let body:String?
let created_at:String?
let updated_at:String?
let closed_at:String?
let merged_at:String?
let merge_commit_sha: String?
let assignee: Assignee?
let assignees: [Assignee]?
let requested_reviewers: [Reviewers]?
let milestone:Milestone?
let commits_url:String?
let review_comments_url:String?
let review_comment_url:String?
let comments_url:String?
let statuses_url:String?
let head:Head?
let base:Base?
let _links:_Links?
let author_association:String?
}
struct PullList:Decodable {
let pulls:[Pull]?
}
/////////////////////////////////////////////////////////
</ code>
1. Celui-ci fonctionne bien avec cette structure: 2. Celui-ci est celui qui donne l'erreur typeMismatch
Vous faites probablement cela maintenant:
let decoder = JSONDecoder()
let repoList = decoder.decode(RepoList.self, from: data)
ce qui convient pour la réponse avec un objet de niveau supérieur.
Pour décoder les réponses JSON qui sont des tableaux de niveau supérieur, utilisez plutôt le code suivant:
let decoder = JSONDecoder()
let repos = decoder.decode([Repo].self, from: data)
Si vous avez une variable JSON
problématique pouvant contenir un nombre ou une chaîne pour certaines clés, vous pouvez décoder un objet sans cette propriété et la définir manuellement après le décodage.
Par exemple, j'ai une classe Vehicle
à l'intérieur de HistoryItem
. Dans Vehicle
model_year
peut être vide String
ou non vide Int
. Ici, je décode modelYear
manuellement en utilisant NSDictionary
et j'essaie d'obtenir Int
. Swift 4
ne peut pas le faire automatiquement.
do {
// Decoding HistoryItem from JSON
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
let decoder = JSONDecoder()
let historyItem = try decoder.decode(HistoryItem.self, from: jsonData)
if let modelYear = (dict as NSDictionary).value(forKeyPath: "vehicle.model_year") as? Int {
historyItem.vehicle?.modelYear = modelYear
}
// Saving HistoryItem to Realm
let realm = try! Realm()
try! realm.write {
realm.add(historyItem, update: true)
}
} catch {
print(error.localizedDescription)
}
Ceci est ma classe Vehicle
qui est contenue dans HistoryItem
:
class Vehicle: Object, Codable {
@objc dynamic var VIN: String = ""
@objc dynamic var make: String?
@objc dynamic var modelName: String?
@objc dynamic var recallCount: Int = 0
@objc dynamic var modelYear: Int = 0
override static func primaryKey() -> String? {
return "VIN"
}
private enum CodingKeys: String, CodingKey {
case VIN = "vin"
case make
case modelName = "model_name"
case recallCount = "recall_count"
}
}
Comme vous le voyez, il n'y a pas de clé model_year
dans CodingKeys
.