将 JSON 日期键映射到 Swift 4 中的结构 [英] Map JSON date keys to a struct in Swift 4
问题描述
我正在尝试解析这个 JSON:
I am trying to parse this JSON:
{
"MetaData": {
"1. Information": "Daily Time Series with Splits and Dividend Events",
"2. Symbol": "AAPL",
"3. Last Refreshed": "2018-06-08",
"4. Output Size": "Compact",
"5. Time Zone": "US/Eastern"
},
"TimeSeries": {
"2018-06-08": {
"1. open": "191.1700",
"2. high": "192.0000",
"3. low": "189.7700",
"4. close": "191.7000",
"5. adjusted close": "191.7000",
"6. volume": "26656799",
"7. dividend amount": "0.0000",
"8. split coefficient": "1.0000"
},
"2018-06-07": {
"1. open": "194.1400",
"2. high": "194.2000",
"3. low": "192.3350",
"4. close": "193.4600",
"5. adjusted close": "193.4600",
"6. volume": "21347180",
"7. dividend amount": "0.0000",
"8. split coefficient": "1.0000"
},
"2018-06-06": {
"1. open": "193.6300",
"2. high": "194.0800",
"3. low": "191.9200",
"4. close": "193.9800",
"5. adjusted close": "193.9800",
"6. volume": "20933619",
"7. dividend amount": "0.0000",
"8. split coefficient": "1.0000"
},
}
}
我想符合这样的结构:
struct Stocks: Decodable {
struct Meta: Decodable {
let info: String
let symbol: String
let last: String
let size: String
let time: String
enum CodingKeys: String, CodingKey {
case info = "1. Information"
case symbol = "2. Symbol"
case last = "3. Last Refreshed"
case size = "4. Output Size"
case time = "5. Time Zone"
}
}
struct Time: Decodable {
let date: String
let price = Prices()
struct Prices: Decodable {
var open: Int?
var high: Int?
var low: Int?
var close: Int?
enum CodingKeys: String, CodingKey {
case open = "1. open"
case high = "2. high"
case low = "3. low"
case close = "4. close"
}
}
}
let MetaData: Meta
let TimeSeries: Time
}
对于元数据部分,它运行良好.但是对于时间序列部分,我不知道如何在不遍历时间序列数据的情况下超越日期.
For the MetaData part it works well. But for the timeseries part I do not know how to get past the dates without just iterating over the TimeSeries data.
我想知道是否有办法将这部分映射到结构体:
I would like to know if there is a way to map this part to a struct:
"TimeSeries": {
"2018-06-08": {
"1. open": "191.1700",
"2. high": "192.0000",
"3. low": "189.7700",
"4. close": "191.7000",
"5. adjusted close": "191.7000",
"6. volume": "26656799",
"7. dividend amount": "0.0000",
"8. split coefficient": "1.0000"
},
"2018-06-07": {
"1. open": "194.1400",
"2. high": "194.2000",
"3. low": "192.3350",
"4. close": "193.4600",
"5. adjusted close": "193.4600",
"6. volume": "21347180",
"7. dividend amount": "0.0000",
"8. split coefficient": "1.0000"
},
"2018-06-06": {
"1. open": "193.6300",
"2. high": "194.0800",
"3. low": "191.9200",
"4. close": "193.9800",
"5. adjusted close": "193.9800",
"6. volume": "20933619",
"7. dividend amount": "0.0000",
"8. split coefficient": "1.0000"
},
}
}
问题似乎是不断变化的日期键 - 如何将它们映射到结构?
The issue seems to be the date keys that keeps changing - how can you map these to a struct?
推荐答案
首先 Prices
中的值是 String
,请注意括起来的双引号.
即使数值是数字,它们也会是Double
,请注意小数点.
First of all the values in Prices
are String
, please note the enclosing double quotes.
And even if the values were numeric, they would be Double
, please note the decimal point.
我的建议是编写一个自定义初始化程序,将键 TimeSeries
的值解码为字典,并将 date
键值对放入 Price代码> 结构(我使用单数形式).最后数组按
date
My suggestion is to write a custom initializer which decodes the value for key TimeSeries
as dictionary and put the date
key-value pair into the Price
struct (I'm using singular form). Finally the array is sorted by date
struct Stocks: Decodable {
enum CodingKeys: String, CodingKey { case timeSeries = "TimeSeries", metaData = "MetaData"}
struct Meta: Decodable {
let info, symbol, last, size, time: String
enum CodingKeys: String, CodingKey {
case info = "1. Information"
case symbol = "2. Symbol"
case last = "3. Last Refreshed"
case size = "4. Output Size"
case time = "5. Time Zone"
}
}
struct Price: Decodable {
var date = ""
let open, high, low, close: String
enum CodingKeys: String, CodingKey {
case open = "1. open"
case high = "2. high"
case low = "3. low"
case close = "4. close"
}
}
let metaData: Meta
let prices : [Price]
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
metaData = try container.decode(Meta.self, forKey: .metaData)
let timeData = try container.decode([String:Price].self, forKey: .timeSeries)
prices = timeData.map({ (key, value) -> Price in
var newPrice = value
newPrice.date = key
return newPrice
}).sorted { $0.date < $1.date }
}
}
这篇关于将 JSON 日期键映射到 Swift 4 中的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!