首页 > 解决方案 > 字典 JSON 的 SWIFT JSON解码器类型不匹配错误

问题描述

尝试将 Json 解析为模型,但显示有关类型不匹配的错误消息。

typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "期望解码 Array 但找到了一个字典。",底层错误: nil))

附加模型,您可以在下面找到 Json。

JSON - http://api.duckduckgo.com/?q=the+wire+characters&format=json

import Foundation
struct RootClass : Codable {
    let type : String?
    let imageWidth : Int?
    let relatedTopics : [RelatedTopics]?
    let answer : String?
    let definitionSource : String?
    let abstractURL : String?
    let meta : Meta?
    let answerType : String?
    let abstractSource : String?
    let imageIsLogo : Int?
    let image : String?
    let heading : String?
    let definitionURL : String?
    let definition : String?
    let infobox : String?
    let redirect : String?
    let results : [String]?
    let abstract : String?
    let imageHeight : Int?
    let entity : String?
    let abstractText : String?

    enum CodingKeys: String, CodingKey {

        case type = "Type"
        case imageWidth = "ImageWidth"
        case relatedTopics = "RelatedTopics"
        case answer = "Answer"
        case definitionSource = "DefinitionSource"
        case abstractURL = "AbstractURL"
        case meta = "meta"
        case answerType = "AnswerType"
        case abstractSource = "AbstractSource"
        case imageIsLogo = "ImageIsLogo"
        case image = "Image"
        case heading = "Heading"
        case definitionURL = "DefinitionURL"
        case definition = "Definition"
        case infobox = "Infobox"
        case redirect = "Redirect"
        case results = "Results"
        case abstract = "Abstract"
        case imageHeight = "ImageHeight"
        case entity = "Entity"
        case abstractText = "AbstractText"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        type = try values.decodeIfPresent(String.self, forKey: .type)
        imageWidth = try values.decodeIfPresent(Int.self, forKey: .imageWidth)
        relatedTopics = try values.decodeIfPresent([RelatedTopics].self, forKey: .relatedTopics)
        answer = try values.decodeIfPresent(String.self, forKey: .answer)
        definitionSource = try values.decodeIfPresent(String.self, forKey: .definitionSource)
        abstractURL = try values.decodeIfPresent(String.self, forKey: .abstractURL)
        meta = try values.decodeIfPresent(Meta.self, forKey: .meta)
        answerType = try values.decodeIfPresent(String.self, forKey: .answerType)
        abstractSource = try values.decodeIfPresent(String.self, forKey: .abstractSource)
        imageIsLogo = try values.decodeIfPresent(Int.self, forKey: .imageIsLogo)
        image = try values.decodeIfPresent(String.self, forKey: .image)
        heading = try values.decodeIfPresent(String.self, forKey: .heading)
        definitionURL = try values.decodeIfPresent(String.self, forKey: .definitionURL)
        definition = try values.decodeIfPresent(String.self, forKey: .definition)
        infobox = try values.decodeIfPresent(String.self, forKey: .infobox)
        redirect = try values.decodeIfPresent(String.self, forKey: .redirect)
        results = try values.decodeIfPresent([String].self, forKey: .results)
        abstract = try values.decodeIfPresent(String.self, forKey: .abstract)
        imageHeight = try values.decodeIfPresent(Int.self, forKey: .imageHeight)
        entity = try values.decodeIfPresent(String.self, forKey: .entity)
        abstractText = try values.decodeIfPresent(String.self, forKey: .abstractText)
    }

}




struct RelatedTopics : Codable {
    let icon : Icon?
    let text : String?
    let result : String?
    let firstURL : String?

    enum CodingKeys: String, CodingKey {

        case icon = "Icon"
        case text = "Text"
        case result = "Result"
        case firstURL = "FirstURL"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        icon = try values.decodeIfPresent(Icon.self, forKey: .icon)
        text = try values.decodeIfPresent(String.self, forKey: .text)
        result = try values.decodeIfPresent(String.self, forKey: .result)
        firstURL = try values.decodeIfPresent(String.self, forKey: .firstURL)
    }

}





struct Developer : Codable {
    let url : String?
    let name : String?
    let type : String?

    enum CodingKeys: String, CodingKey {

        case url = "url"
        case name = "name"
        case type = "type"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        url = try values.decodeIfPresent(String.self, forKey: .url)
        name = try values.decodeIfPresent(String.self, forKey: .name)
        type = try values.decodeIfPresent(String.self, forKey: .type)
    }

}




struct Maintainer : Codable {
    let github : String?

    enum CodingKeys: String, CodingKey {

        case github = "github"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        github = try values.decodeIfPresent(String.self, forKey: .github)
    }

}




struct SrcOptions : Codable {
    let skip_abstract_paren : Int?
    let language : String?
    let is_mediawiki : Int?
    let src_info : String?
    let skip_icon : Int?
    let source_skip : String?
    let min_abstract_length : String?
    let directory : String?
    let skip_end : String?
    let is_fanon : Int?
    let skip_qr : String?
    let skip_abstract : Int?
    let is_wikipedia : Int?
    let skip_image_name : Int?

    enum CodingKeys: String, CodingKey {

        case skip_abstract_paren = "skip_abstract_paren"
        case language = "language"
        case is_mediawiki = "is_mediawiki"
        case src_info = "src_info"
        case skip_icon = "skip_icon"
        case source_skip = "source_skip"
        case min_abstract_length = "min_abstract_length"
        case directory = "directory"
        case skip_end = "skip_end"
        case is_fanon = "is_fanon"
        case skip_qr = "skip_qr"
        case skip_abstract = "skip_abstract"
        case is_wikipedia = "is_wikipedia"
        case skip_image_name = "skip_image_name"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        skip_abstract_paren = try values.decodeIfPresent(Int.self, forKey: .skip_abstract_paren)
        language = try values.decodeIfPresent(String.self, forKey: .language)
        is_mediawiki = try values.decodeIfPresent(Int.self, forKey: .is_mediawiki)
        src_info = try values.decodeIfPresent(String.self, forKey: .src_info)
        skip_icon = try values.decodeIfPresent(Int.self, forKey: .skip_icon)
        source_skip = try values.decodeIfPresent(String.self, forKey: .source_skip)
        min_abstract_length = try values.decodeIfPresent(String.self, forKey: .min_abstract_length)
        directory = try values.decodeIfPresent(String.self, forKey: .directory)
        skip_end = try values.decodeIfPresent(String.self, forKey: .skip_end)
        is_fanon = try values.decodeIfPresent(Int.self, forKey: .is_fanon)
        skip_qr = try values.decodeIfPresent(String.self, forKey: .skip_qr)
        skip_abstract = try values.decodeIfPresent(Int.self, forKey: .skip_abstract)
        is_wikipedia = try values.decodeIfPresent(Int.self, forKey: .is_wikipedia)
        skip_image_name = try values.decodeIfPresent(Int.self, forKey: .skip_image_name)
    }

}

struct Meta : Codable {
    let created_date : String?
    let topic : [String]?
    let src_name : String?
    let status : String?
    let src_options : SrcOptions?
    let producer : String?
    let dev_milestone : String?
    let perl_module : String?
    let dev_date : String?
    let attribution : String?
    let maintainer : Maintainer?
    let blockgroup : String?
    let example_query : String?
    let js_callback_name : String?
    let is_stackexchange : String?
    let description : String?
    let name : String?
    let designer : String?
    let signal_from : String?
    let repo : String?
    let live_date : String?
    let developer : [Developer]?
    let src_id : Int?
    let src_domain : String?
    let tab : String?
    let unsafe : Int?
    let src_url : String?
    let id : String?
    let production_state : String?

    enum CodingKeys: String, CodingKey {

        case created_date = "created_date"
        case topic = "topic"
        case src_name = "src_name"
        case status = "status"
        case src_options = "src_options"
        case producer = "producer"
        case dev_milestone = "dev_milestone"
        case perl_module = "perl_module"
        case dev_date = "dev_date"
        case attribution = "attribution"
        case maintainer = "maintainer"
        case blockgroup = "blockgroup"
        case example_query = "example_query"
        case js_callback_name = "js_callback_name"
        case is_stackexchange = "is_stackexchange"
        case description = "description"
        case name = "name"
        case designer = "designer"
        case signal_from = "signal_from"
        case repo = "repo"
        case live_date = "live_date"
        case developer = "developer"
        case src_id = "src_id"
        case src_domain = "src_domain"
        case tab = "tab"
        case unsafe = "unsafe"
        case src_url = "src_url"
        case id = "id"
        case production_state = "production_state"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        created_date = try values.decodeIfPresent(String.self, forKey: .created_date)
        topic = try values.decodeIfPresent([String].self, forKey: .topic)
        src_name = try values.decodeIfPresent(String.self, forKey: .src_name)
        status = try values.decodeIfPresent(String.self, forKey: .status)
        src_options = try values.decodeIfPresent(SrcOptions.self, forKey: .src_options)
        producer = try values.decodeIfPresent(String.self, forKey: .producer)
        dev_milestone = try values.decodeIfPresent(String.self, forKey: .dev_milestone)
        perl_module = try values.decodeIfPresent(String.self, forKey: .perl_module)
        dev_date = try values.decodeIfPresent(String.self, forKey: .dev_date)
        attribution = try values.decodeIfPresent(String.self, forKey: .attribution)
        maintainer = try values.decodeIfPresent(Maintainer.self, forKey: .maintainer)
        blockgroup = try values.decodeIfPresent(String.self, forKey: .blockgroup)
        example_query = try values.decodeIfPresent(String.self, forKey: .example_query)
        js_callback_name = try values.decodeIfPresent(String.self, forKey: .js_callback_name)
        is_stackexchange = try values.decodeIfPresent(String.self, forKey: .is_stackexchange)
        description = try values.decodeIfPresent(String.self, forKey: .description)
        name = try values.decodeIfPresent(String.self, forKey: .name)
        designer = try values.decodeIfPresent(String.self, forKey: .designer)
        signal_from = try values.decodeIfPresent(String.self, forKey: .signal_from)
        repo = try values.decodeIfPresent(String.self, forKey: .repo)
        live_date = try values.decodeIfPresent(String.self, forKey: .live_date)
        developer = try values.decodeIfPresent([Developer].self, forKey: .developer)
        src_id = try values.decodeIfPresent(Int.self, forKey: .src_id)
        src_domain = try values.decodeIfPresent(String.self, forKey: .src_domain)
        tab = try values.decodeIfPresent(String.self, forKey: .tab)
        unsafe = try values.decodeIfPresent(Int.self, forKey: .unsafe)
        src_url = try values.decodeIfPresent(String.self, forKey: .src_url)
        id = try values.decodeIfPresent(String.self, forKey: .id)
        production_state = try values.decodeIfPresent(String.self, forKey: .production_state)
    }

}


struct Icon : Codable {
    let height : String?
    let uRL : String?
    let width : String?

    enum CodingKeys: String, CodingKey {

        case height = "Height"
        case uRL = "URL"
        case width = "Width"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        height = try values.decodeIfPresent(String.self, forKey: .height)
        uRL = try values.decodeIfPresent(String.self, forKey: .uRL)
        width = try values.decodeIfPresent(String.self, forKey: .width)
    }

}








class Service: NSObject{
    static let shared = Service()

    func fetchCourses(completion: @escaping ([RootClass]?, Error?) -> ()) {
        let urlString = "http://api.duckduckgo.com/?q=the+wire+characters&format=json"
        guard let url = URL(string: urlString) else { return }
        URLSession.shared.dataTask(with: url) { (data, resp, err) in
            if let err = err {
                completion(nil, err)
                print("Failed to fetch courses:", err)
                return
            }

            // check response

            guard let data = data else { return }
            do {
                let courses = try JSONDecoder().decode([RootClass].self, from: data)
                DispatchQueue.main.async {
                    completion(courses, nil)
                }
            } catch let jsonErr {
                print("Failed to decode:", jsonErr)
            }
            }.resume()
    }
}




错误:

解码失败:typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "期望解码 Array 但找到了一个字典。",底层错误: nil))

标签: jsonswiftmodel

解决方案


替换(您的根 json 对象以{}字典而不是数组开头[]

 let courses = try JSONDecoder().decode([RootClass].self, from: data)

let courses = try JSONDecoder().decode(RootClass.self, from: data)

你也不必写 init 因为所有都是可选的

import Foundation
struct RootClass : Codable {
    let type : String?
    let imageWidth : Int?
    let relatedTopics : [RelatedTopics]?
    let answer : String?
    let definitionSource : String?
    let abstractURL : String?
    let meta : Meta?
    let answerType : String?
    let abstractSource : String?
    let imageIsLogo : Int?
    let image : String?
    let heading : String?
    let definitionURL : String?
    let definition : String?
    let infobox : String?
    let redirect : String?
    let results : [String]?
    let abstract : String?
    let imageHeight : Int?
    let entity : String?
    let abstractText : String?

    enum CodingKeys: String, CodingKey {

        case type = "Type"
        case imageWidth = "ImageWidth"
        case relatedTopics = "RelatedTopics"
        case answer = "Answer"
        case definitionSource = "DefinitionSource"
        case abstractURL = "AbstractURL"
        case meta = "meta"
        case answerType = "AnswerType"
        case abstractSource = "AbstractSource"
        case imageIsLogo = "ImageIsLogo"
        case image = "Image"
        case heading = "Heading"
        case definitionURL = "DefinitionURL"
        case definition = "Definition"
        case infobox = "Infobox"
        case redirect = "Redirect"
        case results = "Results"
        case abstract = "Abstract"
        case imageHeight = "ImageHeight"
        case entity = "Entity"
        case abstractText = "AbstractText"
    }

}


struct RelatedTopics : Codable {
    let icon : Icon?
    let text : String?
    let result : String?
    let firstURL : String?

    enum CodingKeys: String, CodingKey {

        case icon = "Icon"
        case text = "Text"
        case result = "Result"
        case firstURL = "FirstURL"
    }

}

struct Developer : Codable {
    let url : String?
    let name : String?
    let type : String?

}

struct Maintainer : Codable {
    let github : String?
}

struct SrcOptions : Codable {
    let skip_abstract_paren : Int?
    let language : String?
    let is_mediawiki : Int?
    let src_info : String?
    let skip_icon : Int?
    let source_skip : String?
    let min_abstract_length : String?
    let directory : String?
    let skip_end : String?
    let is_fanon : Int?
    let skip_qr : String?
    let skip_abstract : Int?
    let is_wikipedia : Int?
    let skip_image_name : Int?

    enum CodingKeys: String, CodingKey {

        case skip_abstract_paren = "skip_abstract_paren"
        case language = "language"
        case is_mediawiki = "is_mediawiki"
        case src_info = "src_info"
        case skip_icon = "skip_icon"
        case source_skip = "source_skip"
        case min_abstract_length = "min_abstract_length"
        case directory = "directory"
        case skip_end = "skip_end"
        case is_fanon = "is_fanon"
        case skip_qr = "skip_qr"
        case skip_abstract = "skip_abstract"
        case is_wikipedia = "is_wikipedia"
        case skip_image_name = "skip_image_name"
    }

}

struct Meta : Codable {
    let created_date : String?
    let topic : [String]?
    let src_name : String?
    let status : String?
    let src_options : SrcOptions?
    let producer : String?
    let dev_milestone : String?
    let perl_module : String?
    let dev_date : String?
    let attribution : String?
    let maintainer : Maintainer?
    let blockgroup : String?
    let example_query : String?
    let js_callback_name : String?
    let is_stackexchange : String?
    let description : String?
    let name : String?
    let designer : String?
    let signal_from : String?
    let repo : String?
    let live_date : String?
    let developer : [Developer]?
    let src_id : Int?
    let src_domain : String?
    let tab : String?
    let unsafe : Int?
    let src_url : String?
    let id : String?
    let production_state : String?

    enum CodingKeys: String, CodingKey {

        case created_date = "created_date"
        case topic = "topic"
        case src_name = "src_name"
        case status = "status"
        case src_options = "src_options"
        case producer = "producer"
        case dev_milestone = "dev_milestone"
        case perl_module = "perl_module"
        case dev_date = "dev_date"
        case attribution = "attribution"
        case maintainer = "maintainer"
        case blockgroup = "blockgroup"
        case example_query = "example_query"
        case js_callback_name = "js_callback_name"
        case is_stackexchange = "is_stackexchange"
        case description = "description"
        case name = "name"
        case designer = "designer"
        case signal_from = "signal_from"
        case repo = "repo"
        case live_date = "live_date"
        case developer = "developer"
        case src_id = "src_id"
        case src_domain = "src_domain"
        case tab = "tab"
        case unsafe = "unsafe"
        case src_url = "src_url"
        case id = "id"
        case production_state = "production_state"
    }

}

struct Icon : Codable {
    let height : String?
    let uRL : String?
    let width : String?

    enum CodingKeys: String, CodingKey {

        case height = "Height"
        case uRL = "URL"
        case width = "Width"
    }

}

推荐阅读