预计解码字典

Posted

技术标签:

【中文标题】预计解码字典【英文标题】:Expected to decode Dictionary 【发布时间】:2020-01-27 07:08:27 【问题描述】:

回应

    [
  
    "result": "success",
    "category": [
      
        "categoryID": "1",
        "category_name": "Health",
        "category_image": "1573456796.jpg",
        "about": "Start your health journey with scientifically developed, guided meditations across below listed verticals",
        "color": "",
        "special": "N",
        "tags": "fitness|energy|strength",
        "is_active": "Y",
        "description": "Explore guided health meditations to build stronger emotional, mental & physical health",
        "added_on": "2019-11-22 03:21:36",
        "no_items": "7"
      ,
      
        "categoryID": "2",
        "category_name": "Work",
        "category_image": "1556794807.jpg",
        "about": "Accelerate your work life with scientifically developed, guided meditations across below listed verticals ",
        "color": "",
        "special": "N",
        "tags": null,
        "is_active": "Y",
        "description": "Explore guided work meditations to release stress, foster progressive mindset & excel at work.",
        "added_on": "2019-05-02 04:30:07",
        "no_items": "2"
      ,
      
        "categoryID": "3",
        "category_name": "Relationships",
        "category_image": "1556794814.jpg",
        "about": "Illuminate your relations with scientifically developed, guided meditations across below listed verticals",
        "color": "",
        "special": "N",
        "tags": null,
        "is_active": "Y",
        "description": "Explore guided relationship meditations to create a deep & loving bond with the self and others",
        "added_on": "2019-05-02 04:30:14",
        "no_items": "0"
      ,
      
        "categoryID": "4",
        "category_name": "Mindfulness",
        "category_image": "1556794819.jpg",
        "about": "Rewire your brain & turn your NOW into WOW™ with scientifically developed, guided mindfulness meditations",
        "color": "",
        "special": "N",
        "tags": null,
        "is_active": "Y",
        "description": "Explore guided mindfulness meditations to develop focus & awareness in order to turn your NOW into WOW™",
        "added_on": "2019-05-02 04:30:19",
        "no_items": "0"
      ,
      
        "categoryID": "5",
        "category_name": "Students",
        "category_image": "1556794824.jpg",
        "about": "Spark up your student life with scientifically developed, guided meditations across below listed verticals ",
        "color": "",
        "special": "N",
        "tags": null,
        "is_active": "Y",
        "description": "Explore guided student meditations to strengthen mind power in order to emerge as a super student",
        "added_on": "2019-05-02 04:30:24",
        "no_items": "0"
      ,
      
        "categoryID": "6",
        "category_name": "Affirmations",
        "category_image": "1556794832.jpg",
        "about": "Prime your mind, body & emotions with scientifically developed, affirmations across below listed verticals.",
        "color": "",
        "special": "N",
        "tags": "tags|testing|search",
        "is_active": "Y",
        "description": "Explore guided affirmations to train your mind & body to unleash the infinite potential within",
        "added_on": "2019-05-02 04:30:32",
        "no_items": "0"
      
    ]
  
]

错误

typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [], debugDescription: “预期解码字典,但找到一个数组 而是。”,基础错误:无))

实施

import Foundation
import Alamofire

struct Library : Codable 
    let result : String?
    let category : [Category]?

    enum CodingKeys: String, CodingKey 

        case result = "result"
        case category = "category"
    

    init(from decoder: Decoder) throws 
        let values = try decoder.container(keyedBy: CodingKeys.self)
        result = try values.decodeIfPresent(String.self, forKey: .result)
        category = try values.decodeIfPresent([Category].self, forKey: .category)
    


struct Category : Codable 
    let categoryID : String?
    let category_name : String?
    let category_image : String?
    let about : String?
    let color : String?
    let special : String?
    let tags : String?
    let is_active : String?
    let description : String?
    let added_on : String?
    let no_items : String?

    enum CodingKeys: String, CodingKey 

        case categoryID = "categoryID"
        case category_name = "category_name"
        case category_image = "category_image"
        case about = "about"
        case color = "color"
        case special = "special"
        case tags = "tags"
        case is_active = "is_active"
        case description = "description"
        case added_on = "added_on"
        case no_items = "no_items"
    

    init(from decoder: Decoder) throws 
        let values = try decoder.container(keyedBy: CodingKeys.self)
        categoryID = try values.decodeIfPresent(String.self, forKey: .categoryID)
        category_name = try values.decodeIfPresent(String.self, forKey: .category_name)
        category_image = try values.decodeIfPresent(String.self, forKey: .category_image)
        about = try values.decodeIfPresent(String.self, forKey: .about)
        color = try values.decodeIfPresent(String.self, forKey: .color)
        special = try values.decodeIfPresent(String.self, forKey: .special)
        tags = try values.decodeIfPresent(String.self, forKey: .tags)
        is_active = try values.decodeIfPresent(String.self, forKey: .is_active)
        description = try values.decodeIfPresent(String.self, forKey: .description)
        added_on = try values.decodeIfPresent(String.self, forKey: .added_on)
        no_items = try values.decodeIfPresent(String.self, forKey: .no_items)
    


extension Library 

    init(data: Data) throws 
        let decoder = JSONDecoder()
        self = try decoder.decode(Library.self, from: data)
    

    init(_ json: String, using encoding: String.Encoding = .utf8) throws 
        guard let data = json.data(using: encoding) else 
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        
        try self.init(data: data)
    

    init(fromURL url: URL) throws 
        try self.init(data: try Data(contentsOf: url))
    

    func jsonData() throws -> Data 
        return try JSONEncoder().encode(self)
    

    func jsonString(encoding: String.Encoding = .utf8) throws -> String? 
        return String(data: try self.jsonData(), encoding: encoding)
    


// MARK: - Alamofire response handlers
extension DataRequest 
    fileprivate func decodableResponseSerializer<T: Decodable>() -> DataResponseSerializer<T> 
        return DataResponseSerializer  _, response, data, error in

            print(response)

            guard error == nil else  return .failure(error!) 

            guard let data = data else 
                return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
            

            return Result  try JSONDecoder().decode(T.self, from: data) 
        
    

    @discardableResult
    fileprivate func responseDecodable<T: Decodable>(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse<T>) -> Void) -> Self 
        return response(queue: queue, responseSerializer: decodableResponseSerializer(), completionHandler: completionHandler)
    

    @discardableResult
    func responsePhoto(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse<Library>) -> Void) -> Self 
        return responseDecodable(queue: queue, completionHandler: completionHandler)
    

【问题讨论】:

@Pratik Sodha 请帮忙 添加您的 API 调用请求代码。 JSON 中最外层的对象是一个数组,而不是字典——正如错误告诉你的那样——你需要解码 [Library].self 而不是 Library.self @Paulw11 self = try decoder.decode([Library].self, from: data) 他们显示错误无法将类型“[库]”的值分配给类型“库” @VarunSinghal 你为什么使用self = ?试试这个代码let result = try JSONDecoder().decode([Library].self, from: data),然后再试试print(result) 【参考方案1】:

您不能将解码分配给 self,因为它的类型不同,我的意思是 self 表示库,但我们正在解码的是库数组,所以。

init(data: Data) throws 
       let decoder = JSONDecoder()
       self = try decoder.decode(Library.self, from: data)
   

示例我已经对字符串进行了响应以便于解析


var stringText = """
[

"result": "success",
"category": [

"categoryID": "1",
"category_name": "Health",
"category_image": "1573456796.jpg",
"about": "Start your health journey with scientifically developed, guided meditations across below listed verticals",
"color": "",
"special": "N",
"tags": "fitness|energy|strength",
"is_active": "Y",
"description": "Explore guided health meditations to build stronger emotional, mental & physical health",
"added_on": "2019-11-22 03:21:36",
"no_items": "7"

]

]
"""
let jsonData = Data(responceString.utf8)

let decoder = JSONDecoder()

do 
    let responceData = try decoder.decode([Library].self, from: jsonData)
    print(responceData)
 catch 
    print(error.localizedDescription)

【讨论】:

我认为这是一种更好的方法,但在catch 中不要使用localizedDescription,因为它给出了更一般的错误描述。请改用print(error) 以获得更好、更详细的错误消息【参考方案2】:

return Result  try JSONDecoder().decode([T].self, from: data) 

而不是

return Result  try JSONDecoder().decode(T.self, from: data) 

【讨论】:

无法将 '[T]' 类型的值转换为闭包结果类型 'T' 。他们给出错误

以上是关于预计解码字典的主要内容,如果未能解决你的问题,请参考以下文章

快速解码 JSON 数组或字典错误

可解码字典 [String : Any] [重复]

当我只想获取字典中的特定值时,如何解码字典值的 JSON 数组?

字符串字典:任何不符合协议“可解码”[重复]

解码错误:typeMismatch“预期解码 Array<Any> 但找到了字典。”

使用包含不同类型字典的 Swift 解码 JSON