Swift - 如何提取具有相同键名的所有值
Swift - How to extract all values with same key names
看了几个 post 我没有找到我要找的东西。我希望这个 post 能帮到我。
我用的是 CoinDesk 的 api,我现在想做的是在答案中检索所有代码(欧元、美元、英镑),但我无法获取所有资产。
{
"time": {
"updated": "Feb 20, 2021 19:48:00 UTC",
"updatedISO": "2021-02-20T19:48:00+00:00",
"updateduk": "Feb 20, 2021 at 19:48 GMT"
},
"disclaimer": "This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
"chartName": "Bitcoin",
"bpi": {
"USD": {
"code": "USD",
"symbol": "$",
"rate": "57,014.5954",
"description": "United States Dollar",
"rate_float": 57014.5954
},
"GBP": {
"code": "GBP",
"symbol": "£",
"rate": "40,681.1111",
"description": "British Pound Sterling",
"rate_float": 40681.1111
},
"EUR": {
"code": "EUR",
"symbol": "€",
"rate": "47,048.5582",
"description": "Euro",
"rate_float": 47048.5582
}
}
}
这是我获取数据的方式
public class NetworkManager {
static public func fetchBPI() {
let url = "https://api.coindesk.com/v1/bpi/currentprice.json"
Alamofire.request(url).responseJSON { response in
switch response.result {
case .success:
print("✅ Success ✅")
if let json = response.data {
do {
let data = try JSON(data: json)
print(data)
let context = PersistentContainer.context
let entity = NSEntityDescription.entity(forEntityName: "BPI", in: context)
let newObject = NSManagedObject(entity: entity!, insertInto: context)
//Date Formatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy HH:mm"
let date = dateFormatter.date(from: data["time"]["updated"].rawValue as! String)
dateFormatter.timeZone = NSTimeZone.local
let timeStamp = dateFormatter.string(from: date ?? Date())
newObject.setValue(timeStamp, forKey: "time")
newObject.setValue(data["chartName"].rawValue, forKey: "chartName")
newObject.setValue(data["bpi"]["EUR"]["symbol"].rawValue, forKey: "symbol")
newObject.setValue(data["bpi"]["EUR"]["rate"].rawValue, forKey: "rate")
newObject.setValue(data["bpi"]["EUR"]["code"].rawValue, forKey: "code")
do {
try context.save()
print("✅ Data saved ✅")
} catch let error {
print(error)
print("❌ Saving Failed ❌")
}
}
catch {
print("❌ Error ❌")
}
}
case .failure(let error):
print(error)
}
}
}
}
我想把所有的代码都输入到bpi密钥中,然后把它们放在一个列表中使用。
您应该使用对象来表示来自服务器的数据。它会是这样的:
struct CoinData: Codable {
let time: Time
let disclaimer, chartName: String
let bpi: BPI
}
struct BPI: Codable {
let usd, gbp, eur: Eur
enum CodingKeys: String, CodingKey {
case usd = "USD"
case gbp = "GBP"
case eur = "EUR"
}
}
struct Eur: Codable {
let code, symbol, rate, eurDescription: String
let rateFloat: Double
enum CodingKeys: String, CodingKey {
case code, symbol, rate
case eurDescription = "description"
case rateFloat = "rate_float"
}
}
struct Time: Codable {
let updated: String
let updatedISO: String
let updateduk: String
}
当你下载数据时,你会像这样解析它:
let coinData = try? JSONDecoder().decode(CoinData.self, from: jsonData)
coinData?.bpi.eur // Access EUR for instance
更新:
使用从服务器获取的数据演示解析的简单演示:
let dataFromServer = "{\"time\":{\"updated\":\"Feb 20, 2021 21:02:00 UTC\",\"updatedISO\":\"2021-02-20T21:02:00+00:00\",\"updateduk\":\"Feb 20, 2021 at 21:02 GMT\"},\"disclaimer\":\"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org\",\"chartName\":\"Bitcoin\",\"bpi\":{\"USD\":{\"code\":\"USD\",\"symbol\":\"$\",\"rate\":\"56,689.8367\",\"description\":\"United States Dollar\",\"rate_float\":56689.8367},\"GBP\":{\"code\":\"GBP\",\"symbol\":\"£\",\"rate\":\"40,449.3889\",\"description\":\"British Pound Sterling\",\"rate_float\":40449.3889},\"EUR\":{\"code\":\"EUR\",\"symbol\":\"€\",\"rate\":\"46,780.5666\",\"description\":\"Euro\",\"rate_float\":46780.5666}}}"
do {
let json = try JSONDecoder().decode(CoinData.self, from: dataFromServer.data(using: .utf8)!)
print(json.bpi.eur) // Will print EUR object
} catch let error {
print(error)
}
我认为这里处理json的最好方法是将“bpi”下的内容当作字典来处理。
struct CoinData: Codable {
let time: Time
let chartName: String
let bpi: [String: BPI]
}
struct BPI: Codable {
let code: String
let rate: Double
enum CodingKeys: String, CodingKey {
case code
case rate = "rate_float"
}
}
struct Time: Codable {
let updated: Date
enum CodingKeys: String, CodingKey {
case updated = "updatedISO"
}
}
我删除了一些不必要的 (?) 属性,还注意到我将 Time
中的 updatedISO
变成了 Date
如果这可能有用,因为它很容易转换.
要正确解码此代码,请使用 try
和 do/catch
,以便正确处理错误。
这是一个例子,我也循环了不同的 currencies/rates
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let result = try decoder.decode(CoinData.self, from: data)
print(result.time.updated)
let coins = result.bpi.values
for coin in coins {
print(coin)
}
} catch {
print(error)
}
输出:
2021-02-20 19:48:00 +0000
BPI(code: "GBP", rate: 40681.1111)
BPI(code: "USD", rate: 57014.5954)
BPI(code: "EUR", rate: 47048.5582)
看了几个 post 我没有找到我要找的东西。我希望这个 post 能帮到我。
我用的是 CoinDesk 的 api,我现在想做的是在答案中检索所有代码(欧元、美元、英镑),但我无法获取所有资产。
{
"time": {
"updated": "Feb 20, 2021 19:48:00 UTC",
"updatedISO": "2021-02-20T19:48:00+00:00",
"updateduk": "Feb 20, 2021 at 19:48 GMT"
},
"disclaimer": "This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
"chartName": "Bitcoin",
"bpi": {
"USD": {
"code": "USD",
"symbol": "$",
"rate": "57,014.5954",
"description": "United States Dollar",
"rate_float": 57014.5954
},
"GBP": {
"code": "GBP",
"symbol": "£",
"rate": "40,681.1111",
"description": "British Pound Sterling",
"rate_float": 40681.1111
},
"EUR": {
"code": "EUR",
"symbol": "€",
"rate": "47,048.5582",
"description": "Euro",
"rate_float": 47048.5582
}
}
}
这是我获取数据的方式
public class NetworkManager {
static public func fetchBPI() {
let url = "https://api.coindesk.com/v1/bpi/currentprice.json"
Alamofire.request(url).responseJSON { response in
switch response.result {
case .success:
print("✅ Success ✅")
if let json = response.data {
do {
let data = try JSON(data: json)
print(data)
let context = PersistentContainer.context
let entity = NSEntityDescription.entity(forEntityName: "BPI", in: context)
let newObject = NSManagedObject(entity: entity!, insertInto: context)
//Date Formatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM-dd-yyyy HH:mm"
let date = dateFormatter.date(from: data["time"]["updated"].rawValue as! String)
dateFormatter.timeZone = NSTimeZone.local
let timeStamp = dateFormatter.string(from: date ?? Date())
newObject.setValue(timeStamp, forKey: "time")
newObject.setValue(data["chartName"].rawValue, forKey: "chartName")
newObject.setValue(data["bpi"]["EUR"]["symbol"].rawValue, forKey: "symbol")
newObject.setValue(data["bpi"]["EUR"]["rate"].rawValue, forKey: "rate")
newObject.setValue(data["bpi"]["EUR"]["code"].rawValue, forKey: "code")
do {
try context.save()
print("✅ Data saved ✅")
} catch let error {
print(error)
print("❌ Saving Failed ❌")
}
}
catch {
print("❌ Error ❌")
}
}
case .failure(let error):
print(error)
}
}
}
}
我想把所有的代码都输入到bpi密钥中,然后把它们放在一个列表中使用。
您应该使用对象来表示来自服务器的数据。它会是这样的:
struct CoinData: Codable {
let time: Time
let disclaimer, chartName: String
let bpi: BPI
}
struct BPI: Codable {
let usd, gbp, eur: Eur
enum CodingKeys: String, CodingKey {
case usd = "USD"
case gbp = "GBP"
case eur = "EUR"
}
}
struct Eur: Codable {
let code, symbol, rate, eurDescription: String
let rateFloat: Double
enum CodingKeys: String, CodingKey {
case code, symbol, rate
case eurDescription = "description"
case rateFloat = "rate_float"
}
}
struct Time: Codable {
let updated: String
let updatedISO: String
let updateduk: String
}
当你下载数据时,你会像这样解析它:
let coinData = try? JSONDecoder().decode(CoinData.self, from: jsonData)
coinData?.bpi.eur // Access EUR for instance
更新:
使用从服务器获取的数据演示解析的简单演示:
let dataFromServer = "{\"time\":{\"updated\":\"Feb 20, 2021 21:02:00 UTC\",\"updatedISO\":\"2021-02-20T21:02:00+00:00\",\"updateduk\":\"Feb 20, 2021 at 21:02 GMT\"},\"disclaimer\":\"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org\",\"chartName\":\"Bitcoin\",\"bpi\":{\"USD\":{\"code\":\"USD\",\"symbol\":\"$\",\"rate\":\"56,689.8367\",\"description\":\"United States Dollar\",\"rate_float\":56689.8367},\"GBP\":{\"code\":\"GBP\",\"symbol\":\"£\",\"rate\":\"40,449.3889\",\"description\":\"British Pound Sterling\",\"rate_float\":40449.3889},\"EUR\":{\"code\":\"EUR\",\"symbol\":\"€\",\"rate\":\"46,780.5666\",\"description\":\"Euro\",\"rate_float\":46780.5666}}}"
do {
let json = try JSONDecoder().decode(CoinData.self, from: dataFromServer.data(using: .utf8)!)
print(json.bpi.eur) // Will print EUR object
} catch let error {
print(error)
}
我认为这里处理json的最好方法是将“bpi”下的内容当作字典来处理。
struct CoinData: Codable {
let time: Time
let chartName: String
let bpi: [String: BPI]
}
struct BPI: Codable {
let code: String
let rate: Double
enum CodingKeys: String, CodingKey {
case code
case rate = "rate_float"
}
}
struct Time: Codable {
let updated: Date
enum CodingKeys: String, CodingKey {
case updated = "updatedISO"
}
}
我删除了一些不必要的 (?) 属性,还注意到我将 Time
中的 updatedISO
变成了 Date
如果这可能有用,因为它很容易转换.
要正确解码此代码,请使用 try
和 do/catch
,以便正确处理错误。
这是一个例子,我也循环了不同的 currencies/rates
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let result = try decoder.decode(CoinData.self, from: data)
print(result.time.updated)
let coins = result.bpi.values
for coin in coins {
print(coin)
}
} catch {
print(error)
}
输出:
2021-02-20 19:48:00 +0000
BPI(code: "GBP", rate: 40681.1111)
BPI(code: "USD", rate: 57014.5954)
BPI(code: "EUR", rate: 47048.5582)