将 JSON 日期键映射到 Swift 4 中的结构 [英] Map JSON date keys to a struct in Swift 4

查看:33
本文介绍了将 JSON 日期键映射到 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆