依赖于 JSON 数据的结构

Posted

技术标签:

【中文标题】依赖于 JSON 数据的结构【英文标题】:Structs depending on JSON data 【发布时间】:2021-01-10 03:26:16 【问题描述】:

我目前正在使用金融市场 API,我可以在其中获取 JSON 数据作为单个股票代码/报价或批量。

如果我知道我要提前从 API 请求什么股票代码,我就能够解码 JSON 数据。

我正在苦苦挣扎的是如何写我的structs,以便我可以解码用户选择的任何股票代码。

例如,在开发中,我知道我想在 AAPL 上请求股票数据,所以我会写适当的 struct(如下),但可以说,在实际部署中,我想看看在 TSLA 股票数据中,在这种情况下,我不会编写适当的 TSLA struct,因为我只有为 AAPL 编写的 struct,因此会收到错误。

有没有办法编写某种动态的struct 或使用 Swift 库来帮助解决这个问题?

我将在下面发布 JSON 数据的 sn-p 和我的struct

"AAPL":
    "quote":
        "symbol":"AAPL",
            "companyName":"Apple, Inc.",
            "primaryExchange":"NASDAQ",
            "calculationPrice":"close",
            "open":112.67,
            "openTime":1600781401038,
            "openSource":"official",
            "close":111.81,
            "closeTime":1600804800589,
            "closeSource":"official",
            "high":112.86,
            "highTime":1600819199980,
            "highSource":"15 minute delayed price",
            "low":109.16,
            "lowTime":1600786957213,
            "lowSource":"15 minute delayed price",
            "latestPrice":111.81,
            "latestSource":"Close",
            "latestTime":"September 22, 2020",
            "latestUpdate":1600804800589,
            "latestVolume":183055373,
            "iexRealtimePrice":111.545,
            "iexRealtimeSize":56,
            "iexLastUpdated":1600806216383,
            "delayedPrice":110.6,
            "delayedPriceTime":1600819199980,
            "oddLotDelayedPrice":127.67,
            "oddLotDelayedPriceTime":1600807552123,
            "extendedPrice":110.6,
            "extendedChange":-1.21,
            "extendedChangePercent":-0.01082,
            "extendedPriceTime":1600819199980,
            "previousClose":110.08,
            "previousVolume":195713815,
            "change":1.73,
            "changePercent":0.01572,
            "volume":183055373,
            "iexMarketPercent":0.007153872636301017,
            "iexVolume":1303096,
            "avgTotalVolume":196415720,
            "iexBidPrice":0,
            "iexBidSize":0,
            "iexAskPrice":0,
            "iexAskSize":0,
            "iexOpen":null,
            "iexOpenTime":null,
            "iexClose":111.8,
            "iexCloseTime":1600804792007,
            "marketCap":1938483513000,
            "peRatio":33.69,
            "week52High":137.98,
            "week52Low":53.15,
            "ytdChange":0.50212,
            "lastTradeTime":1600804799962,
            "isUSMarketOpen":false
        
    ,
    "FB":
    "quote":
        "symbol":"FB",
            "companyName":"Facebook, Inc.",
            "primaryExchange":"NASDAQ",
            "calculationPrice":"close",
            "open":253.31,
            "openTime":1600781400128,
            "openSource":"official",
            "close":254.75,
            "closeTime":1600804800789,
            "closeSource":"official",
            "high":255.32,
            "highTime":1600819191691,
            "highSource":"15 minute delayed price",
            "low":248.22,
            "lowTime":1600787261157,
            "lowSource":"15 minute delayed price",
            "latestPrice":254.75,
            "latestSource":"Close",
            "latestTime":"September 22, 2020",
            "latestUpdate":1600804800789,
            "latestVolume":30401995,
            "iexRealtimePrice":254.695,
            "iexRealtimeSize":100,
            "iexLastUpdated":1600804797803,
            "delayedPrice":253.8,
            "delayedPriceTime":1600819191691,
            "oddLotDelayedPrice":254.74,
            "oddLotDelayedPriceTime":1600804799413,
            "extendedPrice":253.8,
            "extendedChange":-0.95,
            "extendedChangePercent":-0.00373,
            "extendedPriceTime":1600819191691,
            "previousClose":248.15,
            "previousVolume":24709378,
            "change":6.6,
            "changePercent":0.0266,
            "volume":30401995,
            "iexMarketPercent":0.025296103101128724,
            "iexVolume":769052,
            "avgTotalVolume":25154911,
            "iexBidPrice":0,
            "iexBidSize":0,
            "iexAskPrice":0,
            "iexAskSize":0,
            "iexOpen":null,
            "iexOpenTime":null,
            "iexClose":254.695,
            "iexCloseTime":1600804797803,
            "marketCap":725735292113,
            "peRatio":30.89,
            "week52High":304.67,
            "week52Low":137.1,
            "ytdChange":0.241301,
            "lastTradeTime":1600804800789,
            "isUSMarketOpen":false
    


----

struct iexTicker: Decodable 
    let AAPL: iexQuote
    let FB: iexQuote


struct iexQuote: Decodable 
    let quote: iexData

   
struct iexData: Decodable 
    let symbol: String?
    let companyName: String?
    let primaryExchange: String?
    let calculationPrice: String?
    let open: Double?
    let openTime: Double?
    let openSource: String?
    let close: Double?
    let closeTime: Double?
    let closeSource: String?
    let high: Double?
    let highTime: Double?
    let low: Double?
    let lowTime: Double?
    let lowSource: String?
    let latestPrice: Double?
    let latestSource: String?
    let latestTime: String?
    let latestUpdate: Double?
    let latestVolume: Double?
    let iexRealtimePrice: Double?
    let iexRealtimeSize: Double?
    let iexLastUpdated: Double?
    let delayedPrice: Double?
    let delayedPriceTime: Double?
    let oddLotDelayedPrice: Double?
    let oddLotDelayedPriceTime: Double?
    let extendedPrice: Double?
    let extendedChange: Double?
    let extendedChangePercent: Double?
    let extendedPriceTime: Double?
    let previousClose: Double?
    let previousVolume: Double?
    let change: Double?
    let changePercent: Double?
    let volume: Double?
    let iexMarketPercent: Double?
    let iexVolume: Double?
    let avgTotalVolume: Double?
    let iexBidPrice: Double?
    let iexBidSize: Double?
    let iexAskPrice: Double?
    let iexAskSize: Double?
    let iexOpen: Double?
    let iexOpenTime: Double?
    let iexClose: Double?
    let iexCloseTime: Double?
    let marketCap: Double?
    let peRatio: Double?
    let week52High: Double?
    let week52Low: Double?
    let ytdChange: Double?
    let lastTradeTime: Double?
    let isUSMarketOpen: Bool?

【问题讨论】:

AAPL 和 TSLA 的结构不一样吗?看起来您只需要解码[TickerName: IEXQuote] 类型的字典(其中TickerName 只是String 的别名) 我认为您缺少 JSON 的某些部分。我怀疑开头应该是 "APPL": "quote": "symbol":"AAPL", ... , "FB": ... ,而您离开了最初的 "APPL": 部分。 【参考方案1】:

有什么办法可以写出某种动态结构

没有。但是您可以为每种类型的 JSON 编写不同的结构,然后将数据吸入一些更通用的类型。例如,如果您有两个结构,Ticker1Data 和 Ticker2Data,那么您可以有一个枚举 AnyTicker,其案例具有 Ticker1Data 和 Ticker2Data 作为关联类型:

enum AnyTicker 
    case ticker1(Ticker1Data)
    case ticker2(Ticker2Data)

现在单个 AnyTicker 实例将保存 Ticker1Data 或 Ticker2Data。一旦你有一个枚举实例,你就可以找出它是什么情况,现在关联的数据自动属于正确的类型。

【讨论】:

以上是关于依赖于 JSON 数据的结构的主要内容,如果未能解决你的问题,请参考以下文章

JSON —— 数据结构

json数据结构

使用 package.json 依赖项作为 gulpfile.js 中的文件夹结构

Composer 的结构详解

Json数据结构认识

Yarn 本地包依赖项