【问题标题】:attempt at parsing JSON file in Swift 5 ("Expected to decode Array<Any> but found a dictionary instead.")尝试在 Swift 5 中解析 JSON 文件(“预期解码 Array<Any> 但找到了字典。”)
【发布时间】:2021-11-06 04:16:45
【问题描述】:

我正在尝试为与大学相关的工作制作一个股票应用程序,除了将股票的实际数据输入我的应用程序之外,我几乎完成了我需要做的所有事情,过去几天我一直在尝试和研究但仍然无法让它工作,因为我收到错误消息:

typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath: [], debugDescription: "本应解码 Array 但找到了字典。", underlyingError: nil))

感谢任何帮助,因为这是我使用 swift/xcode 所做的第一件事

我的 viewController 中的代码:

import UIKit

class ViewController: UIViewController { 
    
    override func viewDidLoad() {
        super.viewDidLoad()
        fetchPostData { (posts) in
            for post in posts {
                print(post.datetime!)
            }
        }                
    }
    
    func fetchPostData(completionHandler: @escaping ([Post]) -> Void) {
        
        let url = URL(string: "https://api.twelvedata.com/time_series?symbol=AAPL&interval=1min&apikey=<api-key>")!
        
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            
            guard let data = data else { return }
            
            do {
                let postsData = try JSONDecoder().decode([Post].self, from: data)
                
                completionHandler(postsData)
                
            }
            catch {
                let error = error
                print(error)
            }                                                        
        }.resume()        
    }        
} 

以及其他带有变量的文件:


struct Post: Codable {
    var datetime: Int!
    var open: Int!
    var high: String!
    var low: String!
    var close: String!
    var volume: String!
}

json 文件链接:https://api.twelvedata.com/time_series?symbol=AAPL&interval=1min&apikey=0561a81a9baf4ae4bc65c7af9196f929

【问题讨论】:

  • 需要解码完整的json消息,中途不能启动。要了解如何形成用于解码的结构,请使用quicktype.io
  • 不相关但从未将结构成员声明为隐式未包装的选项 (!)。如果您想要可选项声明常规可选项 (?),否则即使没有感叹号,代码也会编译。
  • 在真正拥有Post之前缺少顶级:meta & values 键...
  • 提示:let reversed = [Post(datatime: 3, open: 2, ...), Post(datatime:...)]; let encoded = try! JSONEncoder().encode(reversed); print(String(data: encoded, encoding: .utf8)!),并查看输出。正好相反,所以它应该看起来像您收到的 JSON 以使用decode([Post].self 解码。不一样,它缺少“元”和“值”,正如所说的......

标签: ios arrays json swift xcode


【解决方案1】:

错误不言自明;您正在尝试解码数组,但 JSON 是字典。您需要更改解码:

JSONDecoder().decode(Post.self, from: data)

编辑在 Joakim Danielson 提示完整答案后:

您还必须修改您的结构,以便在您的响应中容纳 JSON

struct Post: Decodable {
    let meta: Meta
}

struct Meta: Decodable {
    let symbol: String
    let interval: String
    let currency: String
    let values: [Values]
    // more data here
}

struct Values: Decodable {
    // more data here
}

【讨论】:

  • 已经尝试了几次,但仍然无法正常工作:/
【解决方案2】:

首先,Post中的all值为String,请注意JSON中的双引号

struct Post: Decodable {
    let datetime, open, high, low, close, volume: String
}

但主要问题是 - 正如 cmets 和 Alastar 的回答中提到的以及错误间接说明的那样 - 您忽略了根对象。您必须始终从顶部解码 JSON。添加这个结构

struct Root: Decodable {
    let status: String
    let values: [Post]
}

解码

let postsData = try JSONDecoder().decode(Root.self, from: data)
completionHandler(postsData.values)
            

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多