Swift IOS 无法使用 Codable 访问 json 数组数据

Posted

技术标签:

【中文标题】Swift IOS 无法使用 Codable 访问 json 数组数据【英文标题】:Swift IOS Failed to access json array data using Codable 【发布时间】:2019-12-04 18:20:56 【问题描述】:

如何使用 Codable 访问 JSON。这是我的示例 json。


    "status": "success",
    "message": "Data received successfully",
    "course": 
        "id": 1,
        "description": "something",
        "name": "ielts",
        "attachments": [
            
                "id": 809,
                "attachment": "https:--",
                "file_name": "syllabus.pdf",
                "description": "course",

            ,
            
                "id": 809,
                "attachment": "https:--",
                "file_name": "syllabus.pdf",
                "description": "course",
            ]
        "upcased_name": "IELTS"
     

这是我的代码。

struct ResponseObject: Codable 
    let course: [Course]


struct Course: Codable 
    let id: Int
    let name: String
    let description: String
    let attachments: [Attachments]


struct Attachments: Codable 
    let id: Int
    let attachment: String
    let file_name: String
    let description: String
    let about: String


var course: [Course] = []

这是我的 api 调用。

func fetchUserData() 

    let headers: HTTPHeaders = [
        "Authorization": "Token token="+UserDefaults.standard.string(forKey: "auth_token")!,
        "Accept": "application/json"
    ]
    let params = ["course_id" : "1"] as [String : AnyObject]
    self.showSpinner("Loading...", "Please wait!!")
    DispatchQueue.global(qos: .background).async 
        AF.request(SMAConstants.courses_get_course_details , parameters: params, headers:headers ).responseDecodable(of: ResponseObject.self, decoder: self.decoder)  response in

            DispatchQueue.main.async 
                self.hideSpinner()
                guard let value = response.value else 
                    print(response.error ?? "Unknown error")
                    return
                

                self.course = value.course
            
        
    

我收到以下错误。

responseSerializationFailed(原因: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(错误: Swift.DecodingError.typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "course", intValue: nil)], debugDescription: "预计解码 数组,但找到了字典。”,基础错误:无))))

【问题讨论】:

阅读错误信息。 course 的值不是数组,而是字典(单个对象)。而且Attachment中没有about 您应该测试较小的代码片段;例如,在这里,当您进行 API 调用时,您会发现您的 Codable 内容已损坏。如果相反,例如,您在项目中包含一些测试 JSON,然后通过从包中加载它来对其进行解码,那么一旦您确定可以继续进行 API 调用,这将非常有帮助。 【参考方案1】:

您的模型对象与 JSON 结构不匹配。试试这个:

struct ResponseObject: Codable 
    let status, message: String
    let course: Course


struct Course: Codable 
    let id: Int
    let courseDescription, name: String
    let attachments: [Attachment]
    let upcasedName: String

    enum CodingKeys: String, CodingKey 
        case id
        case courseDescription = "description"
        case name, attachments
        case upcasedName = "upcased_name"
    


struct Attachment: Codable 
    let id: Int
    let attachment, fileName, attachmentDescription: String

    enum CodingKeys: String, CodingKey 
        case id, attachment
        case fileName = "file_name"
        case attachmentDescription = "description"
    

要使用普通的 Swift 和 Foundation 下载和解析它,请使用如下代码:

let url = URL(string: SMAConstants.courses_get_course_details)!
let task = URLSession.shared.dataTask(with: url)  data, response, error in
    if let error = error 
        print(error)
        return
    

    if let data = data 
      do 
        let response = try JSONDecoder().decode(ResponseObject.self, from: data)
        // access your data here
       catch 
         print(error)
      
    

task.resume()

【讨论】:

我试过我得到这个错误。 responseSerializationFailed(原因: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(错误: Swift.DecodingError.keyNotFound(CodingKeys(stringValue: "file_name", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "course", intValue: nil), CodingKeys(stringValue: "attachments", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"file_name\" , intValue: nil) (\"file_name\").", underlyingError: nil)))) 错误信息非常准确:您的课程附件不包含“file_name”。将fileName 属性设为可选以处理这种情况。 你能告诉我如何在 Alamofire 请求中使用这些值吗? 我要尝试返回 attachments.count 但它不起作用,以及如何将它用于 tableview 单元格。 获取计数应该像responseObject.course.attachments.count 一样简单。我还建议不要为此使用像 Alamofire 这样的大型库,因为只需几行简单的 Swift 代码和 Foundation 工具就可以完成这项工作。将数据放入 tableview 是完全不同的事情,应该在一个单独的问题中提出,一旦您完成了此处众多且现成的教程和问题之一。

以上是关于Swift IOS 无法使用 Codable 访问 json 数组数据的主要内容,如果未能解决你的问题,请参考以下文章

使用 Codable 使用 Swift 归档

Swift4 中的 Codable 和 XMLParser

如何使用 Swift 创建 JSON Codable [关闭]

如何从 iOS Swift Codable 中的 API 响应通知或打印模型类上缺少的密钥?

在 swift 中对动态键和动态对象使用 Codable

Swift 4 Codable - API 有时提供 Int 有时提供 String