Ios 解码JSON错误“;但却找到了一本字典;

Ios 解码JSON错误“;但却找到了一本字典;,ios,json,swift,api,Ios,Json,Swift,Api,我正在使用api制作今天iOS应用程序的历史记录 以下是我的数据结构: struct HistoryAPIResponse: Codable { let data: [Events] } struct Events: Codable { let year: String let text: String let html: String } 这就是我如何从中获取数据: 导入UIKit final class HistoryAPICaller {

我正在使用api制作今天iOS应用程序的历史记录

以下是我的数据结构:

struct HistoryAPIResponse: Codable  {    
    let data: [Events]
}

struct Events: Codable {
    let year: String
    let text: String
    let html: String
}
这就是我如何从中获取数据: 导入UIKit

final class HistoryAPICaller {
    static let shared = HistoryAPICaller()
    
    struct Constants {
        static let topHeadLinesURL = URL(string:
            "http://history.muffinlabs.com/date/4/19"
            )
        
        static let searchUrlString =
        
        "http://history.muffinlabs.com/date/4/19"
        
        
    }
    
    private init() {}
        
        public func getTopStories(completion: @escaping (Result<[Events], Error>) -> Void) {
            
            guard let html = Constants.topHeadLinesURL else {
                return
            }
            
            let task = URLSession.shared.dataTask(with: html) { data, _, error in
                
                if let error = error {
                    completion(.failure(error))
                }
                
                else if let data = data {
                    do {
                        _ = try JSONDecoder().decode(HistoryAPIResponse.self, from: data)           
                    }
                    catch {
                        completion(.failure(error))
                    }
            }
        }
            task.resume()
    }

    
    
    public func search(with query: String, completion: @escaping (Result<[Events], Error>) -> Void) {
        guard !query.trimmingCharacters(in: .whitespaces).isEmpty else {
            return
        }
        
        
        let urltring = Constants.searchUrlString + query
        guard let html = URL(string:urltring) else {
            return
        }
        
        let task = URLSession.shared.dataTask(with: html) { data, _, error in
            
            if let error = error {
                completion ( .failure(error))    
            }
            
            
            else if let data = data {
                do {
                    _ = try JSONDecoder().decode(HistoryAPIResponse.self, from: data)    
                }
                catch {
                    completion (.failure(error))   
                }
            }
        }
        task.resume()
    }
    
}
final class HistoryAPICaller{
静态let shared=HistoryAPICaller()
结构常数{
静态let topHeadLinesURL=URL(字符串:
"http://history.muffinlabs.com/date/4/19"
)
静态let searchUrlString=
"http://history.muffinlabs.com/date/4/19"
}
私有init(){}
public func getTopStories(完成:@escaping(Result)->Void){
guard let html=Constants.topHeadLinesURL else{
回来
}
让task=URLSession.shared.dataTask(with:html){data,\中出现错误
如果let error=error{
完成(.failure(error))
}
如果let data=data,则为else{
做{
_=尝试JSONDecoder().decode(HistoryAPIResponse.self,from:data)
}
抓住{
完成(.failure(error))
}
}
}
task.resume()
}
公共函数搜索(带查询:字符串,完成:@escaping(Result)->Void){
guard!query.trimmingCharacters(在:。空格中)。isEmpty else{
回来
}
设urltring=Constants.searchUrlString+query
guard let html=URL(字符串:urltring)else{
回来
}
让task=URLSession.shared.dataTask(with:html){data,\中出现错误
如果let error=error{
完成(.failure(error))
}
如果let data=data,则为else{
做{
_=尝试JSONDecoder().decode(HistoryAPIResponse.self,from:data)
}
抓住{
完成(.failure(error))
}
}
}
task.resume()
}
}
其中一条错误信息显示: 类型不匹配(Swift.Array,Swift.DecodingError.Context(codingPath:[CodingKeys(stringValue:“data”,intValue:nil)],debugDescription:“应解码数组,但找到了字典。”,underyingerror:nil))

我有点理解问题的本质,数据就是一本字典。但我不知道如何解决它,因为这是API的结构,所有东西都存储在[数据]中

你知道如何解决这个问题吗?提前感谢您的帮助。

您需要帮助

let res = try JSONDecoder().decode(Root.self, from: data)           

让数据:[Events]
出错。在访问
Events
之前,您会看到JSON中有一个键
Events
,它缺少一个步骤。
struct HistoryAPIResponse:Codable{let data:HistoryAPIResponse}struct HistoryAPIResponse:Codable{let Events:[Events]}
应该可以做到这一点。但最好通过设置自定义编码键或键策略来命名
let events
而不是let
events
。如果不需要中间结构,也可以使用自定义的
init(解码器:)
。谢谢您的帮助。数据结果正常,但现在我在将获取的数据返回tableView时遇到了问题。我现在使用do{let result=try JSONDecoder().decode(HistoryAPIResponse.self,from:data)print(“Articles:(result.data.count)”)completion(.success(result.data))}catch{completion(.failure(error))}它表示“HistoryDataAPIResponse”类型的值没有成员“count”,无法将“HistoryDataAPIResponse”类型的值转换为预期的参数类型“[Events]现在是
result.data.Events.count
谢谢你的回答,这个也可以!
struct Root: Codable  {    
    let data: HistoryAPIResponse
}

struct HistoryAPIResponse: Codable  {    
    let events: [Events] 
    private enum CodingKeys : String, CodingKey {
        case events = "Events" 
    }
}

struct Events: Codable {
    let year,text,html: String 
}