0

I try to decode a JSON of this structure:

https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=5min&apikey=demo

The "Time Series (5min)" Object is a dictionary of Objects, but I don't know how to decode this JSON using the Codable Protocol when the keys of the dictionary are changing whenever I load the JSON.

I tried to write some models, but whenever I try to access the dictionary I get nil.


struct stock: Decodable{
    let function: Function?
    enum CodingKeys: String, CodingKey {
        case function = "Time Series (5min)"
    }
}

struct Function: Decodable{
    let values: [String:Value]
}

struct Value: Decodable{
    let open: String
    let heigh: String
    let low: String
    let close: String
    let volume: String
    enum CodingKeys: String, CodingKey{
        case open = "1.open"
        case heigh = "2. heigh"
        case low = "3. low"
        case close = "4.close"
        case volume = "5.volume"
    }
}

How can I write my code in a way that I don't need to know the keys in advance, but also get them at the end to display the data with the correct date. Thank you

focafull
  • 3
  • 1
  • Maybe this can help you. https://stackoverflow.com/questions/45598461/swift-4-decodable-with-keys-not-known-until-decoding-time – vpoltave Aug 19 '19 at 11:39
  • Related: [Map JSON date keys to a struct in Swift 4](https://stackoverflow.com/questions/51234248/map-json-date-keys-to-a-struct-in-swift-4/51234507#51234507) which maps the dictionaries to an array and puts the date into the struct – vadian Aug 19 '19 at 11:48

2 Answers2

0

You an simply create your Stock and Value models like,

struct Stock: Decodable {
    let timeSeries: [String:Value]

    enum CodingKeys: String, CodingKey {
        case timeSeries = "Time Series (5min)"
    }
}

struct Value: Decodable {
    let open: String
    let high: String
    let low: String
    let close: String
    let volume: String

    enum CodingKeys: String, CodingKey{
        case open = "1. open"
        case high = "2. high"
        case low = "3. low"
        case close = "4. close"
        case volume = "5. volume"
    }
}

There is no need for separate struct Function.

Parse your response using JSONDecoder like,

do{
    let response = try JSONDecoder().decode(Stock.self, from: data)
    print(response)
} catch {
    print(error)
}
PGDev
  • 23,751
  • 6
  • 34
  • 88
0

you can use https://app.quicktype.io to create Codable models fast and easy. For example the following code is generated using that service with the response of that request you need. I didn't check it but should work fine.

// This file was generated from JSON Schema using quicktype, do not modify it directly.
// To parse the JSON, add this file to your project and do:
//
//   let stock = try? JSONDecoder().decode(Stock.self, from: jsonData)

import Foundation

// MARK: - Stock
struct Stock: Codable {
    let metaData: MetaData
    let timeSeries5Min: [String: TimeSeries5Min]

    enum CodingKeys: String, CodingKey {
        case metaData = "Meta Data"
        case timeSeries5Min = "Time Series (5min)"
    }
}

// MARK: - MetaData
struct MetaData: Codable {
    let the1Information, the2Symbol, the3LastRefreshed, the4Interval: String
    let the5OutputSize, the6TimeZone: String

    enum CodingKeys: String, CodingKey {
        case the1Information = "1. Information"
        case the2Symbol = "2. Symbol"
        case the3LastRefreshed = "3. Last Refreshed"
        case the4Interval = "4. Interval"
        case the5OutputSize = "5. Output Size"
        case the6TimeZone = "6. Time Zone"
    }
}

// MARK: - TimeSeries5Min
struct TimeSeries5Min: Codable {
    let the1Open, the2High, the3Low, the4Close: String
    let the5Volume: String

    enum CodingKeys: String, CodingKey {
        case the1Open = "1. open"
        case the2High = "2. high"
        case the3Low = "3. low"
        case the4Close = "4. close"
        case the5Volume = "5. volume"
    }
}
Dmitry
  • 2,963
  • 2
  • 21
  • 39