Swift JSON解码器类型不匹配错误
Posted
技术标签:
【中文标题】Swift JSON解码器类型不匹配错误【英文标题】:Swift JSONDecoder typeMismatch error 【发布时间】:2017-12-29 13:06:00 【问题描述】:我正在尝试使用 JSONDecoder 将 JSON 转换为 Swift 中的结构,所以我编写了所有结构,修改了几个小时,它仍然给我这个错误。我不知道是否有办法看到给出这个的线。 我将在下面发布我的结构和 Json 文件链接。
完整的错误描述是:
typeMismatch(Swift.Dictionary
, Swift.DecodingError.Context(codingPath: [], debugDescription: “应解码 Dictionary 但找到一个数组 而是。”,基础错误:无))
// 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]?
/////////////////////////////////////////////////////////
1.This one is working fine with this structs: 2.This one is the one that gives the typeMismatch error
【问题讨论】:
不工作的是Array
第一个 JSON 有一个字典作为***对象,第二个 JSON 有一个数组——正如错误消息清楚地表明的那样。
【参考方案1】:
你现在可能正在这样做:
let decoder = JSONDecoder()
let repoList = decoder.decode(RepoList.self, from: data)
这对于***对象的响应很好。
要解码***数组的 JSON 响应,请改用如下代码:
let decoder = JSONDecoder()
let repos = decoder.decode([Repo].self, from: data)
【讨论】:
我遇到了同样的问题。我从 api 询问单个 json 对象,但即使对于单个 json 对象,api 的结果也总是带有数组。这就是为什么你需要像第二个那样修复你的代码,然后拿第一个并返回它。【参考方案2】:如果您有一个有问题的JSON
,它可能包含一些键的数字或字符串,您可以解码没有该属性的对象并在解码后手动设置该属性。
例如,我在HistoryItem
中有一个Vehicle
类。在Vehicle
model_year
可以为空String
或非空Int
。在这里,我正在使用NSDictionary
手动解码modelYear
并尝试获取Int
。 Swift 4
无法自动完成。
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)
这是我的Vehicle
类,包含在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"
如您所见,CodingKeys
中没有 model_year
键。
【讨论】:
以上是关于Swift JSON解码器类型不匹配错误的主要内容,如果未能解决你的问题,请参考以下文章
当您不知道 Swift 中的项目类型时,如何解码嵌套的 JSON 数据? [复制]
通过使用 Alamofire 和解码获取 JSON - Swift 4