gpt4 book ai didi

json - 如何使用 Swift 结构正确解码嵌套的 JSON 对象

转载 作者:搜寻专家 更新时间:2023-10-31 19:31:57 30 4
gpt4 key购买 nike

意图:

通过Coinmarketcap API接收加密货币价格数据,将其解码为 SWIFT 中的自定义结构,并可能将该数据存储在数据库中(CoreData 或 SQLite)。

上下文:

我在 JSONDecoder().decode 上收到以下错误:

Error serializing json: typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "status", intValue: nil), _DictionaryCodingKey(stringValue: "credit_count", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Any> but found a number instead.", underlyingError: nil))

问题:

  1. 如何正确解释该错误?我解码错了什么?
  2. 我收到的数据格式是否正确?看起来不像正确的 JSON。

代码:

import UIKit
import PlaygroundSupport


// Defining structures

struct RootObject: Decodable {
let status: [String: StatusObject?]
let data: DataObject?
}

struct StatusObject: Decodable {
let credit_count: Int?
let elapsed: Int?
let error_code: Int?
let timestamp: String?
}

struct DataObject: Decodable {
let amount: Int?
let id: Int?
let last_updated: String?
let name: String?
let quote: [QuoteObject]?
let symbol: String?
}

struct QuoteObject: Decodable {
let usd: String?
}

struct usdObject: Decodable {
let last_updated: String?
let price: String?
}


//Configuring URLSession

let config = URLSessionConfiguration.default

config.httpAdditionalHeaders = ["X-CMC_PRO_API_KEY": "<removed>",
"Accept": "application/json",
"Accept-Encoding": "deflate, gzip"]

let session = URLSession(configuration: config)

let url = URL(string: "https://sandbox-api.coinmarketcap.com/v1/tools/price-conversion?convert=USD&amount=1&symbol=BTC")!


//Making and handling a request

let task = session.dataTask(with: url) { data, response, error in

guard error == nil else {
print ("error: \(error!)")
return
}

guard let content = data else {
print("No data")
return
}

//Serializing and displaying the received data
guard let json = (try? JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any]
else {
print("Not containing JSON")
return
}

print(json)

//Trying to decode
do {
let prices = try JSONDecoder().decode(RootObject.self, from: data!)
print(prices)
} catch let decodeError {
print("Error serializing json:", decodeError)
}
}

task.resume()

数据响应及报错:

["status": {
"credit_count" = 1;
elapsed = 6;
"error_code" = 0;
"error_message" = "<null>";
timestamp = "2019-02-16T11:10:22.147Z";
}, "data": {
amount = 1;
id = 1;
"last_updated" = "2018-12-22T06:08:23.000Z";
name = Bitcoin;
quote = {
USD = {
"last_updated" = "2018-12-22T06:08:23.000Z";
price = "3881.88864625";
};
};
symbol = BTC;
}]
Error serializing json: typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "status", intValue: nil), _DictionaryCodingKey(stringValue: "credit_count", intValue: nil)], debugDescription: "Expected to decode Dictionary<String, Any> but found a number instead.", underlyingError: nil))

编辑 1:

正确序列化的 JSON:

{
"status": {
"timestamp": "2019-02-16T18:54:05.499Z",
"error_code": 0,
"error_message": null,
"elapsed": 6,
"credit_count": 1
},
"data": {
"id": 1,
"symbol": "BTC",
"name": "Bitcoin",
"amount": 1,
"last_updated": "2018-12-22T06:08:23.000Z",
"quote": {
"USD": {
"price": 3881.88864625,
"last_updated": "2018-12-22T06:08:23.000Z"
}
}
}
}

最佳答案

结构中有很多问题。

主要问题是 data 的值是一个字典,它被解码为一个结构而不是另一个字典。其他问题是 id 的类型是 String 并且 priceDouble

Coinmarketcap 等 API 发送可靠数据,因此不要将所有内容都声明为可选。删除问号。

下面的结构能够解码 JSON。由于键改变,引号被解码成字典。添加 .convertFromSnakeCase key 解码策略以获取 camelCased key 。通过添加适当的日期解码策略,日期被解码为 Date

我删除了所有那些多余的 ...Object 出现,除了 DataObject 因为 Data 结构已经存在。

struct Root: Decodable {
let status: Status
let data: DataObject
}

struct Status: Decodable {
let creditCount: Int
let elapsed: Int
let errorCode: Int
let timestamp: Date
}

struct DataObject: Decodable {
let amount: Int
let id: String
let lastUpdated: Date
let name: String
let quote: [String:Quote]
let symbol: String
}

struct Quote: Decodable {
let lastUpdated: Date
let price: Double
}


//Trying to decode
do {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .formatted(dateFormatter)
let result = try decoder.decode(Root.self, from: data!)
let quotes = result.data.quote
for (symbol, quote) in quotes {
print(symbol, quote.price)
}
} catch {
print(error)
}

关于json - 如何使用 Swift 结构正确解码嵌套的 JSON 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54722657/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com