预期解码 Array<Any> 但找到了字典
Posted
技术标签:
【中文标题】预期解码 Array<Any> 但找到了字典【英文标题】:Expected to decode Array<Any> but found a dictionary instead 【发布时间】:2017-12-28 12:14:49 【问题描述】:我从返回数组的 API 获取数据,但需要用具有“子级别”的 API 替换它:
RAW:
ETH:
USD:
TYPE: "5"
MARKET: "CCCAGG"
FROMSYMBOL: "ETH"
TOSYMBOL: "USD"
PRICE: 680.89
CHANGEPCT24HOUR : -9.313816893529749
这是我的结构:
struct Ethereum: Codable
let percentChange24h: String
let priceUSD: String
private enum CodingKeys: String, CodingKey
case priceUSD = "PRICE", percentChange24h = "CHANGEPCT24HOUR"
以及实现:
func fetchEthereumInfo(completion: @escaping (Ethereum?, Error?) -> Void)
let url = URL(string: "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD")!
let task = URLSession.shared.dataTask(with: url) (data, response, error) in
guard let data = data else return
do
if let ethereumUSD = try JSONDecoder().decode([Ethereum].self, from: data).first
print(ethereumUSD)
completion(ethereumUSD, nil)
catch
print(error)
task.resume()
控制台打印typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))
我真的不知道要在我的代码中更新什么或这种形式的 API 是什么
【问题讨论】:
【参考方案1】:首先 JSON 不包含任何数组。阅读 JSON 非常容易。只有 2(两个!)集合类型,数组 []
和字典 。如您所见,JSON 字符串中根本没有方括号。
任何(子)字典 都必须解码为自己的类型,所以它应该是
struct Root : Decodable
private enum CodingKeys : String, CodingKey case raw = "RAW"
let raw : RAW
struct RAW : Decodable
private enum CodingKeys : String, CodingKey case eth = "ETH"
let eth : ETH
struct ETH : Decodable
private enum CodingKeys : String, CodingKey case usd = "USD"
let usd : USD
struct USD : Decodable
private enum CodingKeys : String, CodingKey
case type = "TYPE"
case market = "MARKET"
case price = "PRICE"
case percentChange24h = "CHANGEPCT24HOUR"
let type : String
let market : String
let price : Double
let percentChange24h : Double
要解码 JSON 并打印 percentChange24h
,您必须编写
let result = try JSONDecoder().decode(Root.self, from: data)
print("percentChange24h", result.raw.eth.usd.percentChange24h)
【讨论】:
非常感谢瓦迪安!这正是我一直在寻找的。result.raw.eth.usd.percentChange24h
有更简单的语法吗?
你可以在Root
中声明一个计算变量来得到raw.eth.usd
太好了,顺便说一句,我在let result
线上收到了Initializer for conditional binding must have Optional type, not 'Root'
。我想保留我的 do-catch 方法,那么我该如何摆脱错误?
不要if let
,如果解码成功则结果是非可选的
别忘了告诉 OP 在 catch 内和守卫 else 括号内调用完成 completion(nil, error)
以上是关于预期解码 Array<Any> 但找到了字典的主要内容,如果未能解决你的问题,请参考以下文章
debugDescription:“预期解码 Array<Any>,但找到了字典。”,underlyingError:nil)
Swift 4 JSON Parsing(预期解码 Array<Any> 但找到了字典)
解析 JSON 错误“预期解码 Array<Any> 但找到了一个数字
预期解码 Dictionary<String, Any> 但找到一个数组而不是 JSON SwiftUI