Home > Enterprise >  How do I unitize a variable in structure that is of type structure
How do I unitize a variable in structure that is of type structure

Time:09-28

I have been working with reading JSON files. With help I have been able to do so but now want to expand what I read from the JSON file. I think I have the structures set up correctly but do not understand how to initialize the metaData variable in the Stock structure when I create an instance of the structure from the ReadData class. I have placed ?'s in the line of code in the ReadData that is giving me problems Any help would be appreciated. Chris Below is the JSON data and my code.

"Meta Data": {
    "1. Information": "Daily Prices (open, high, low, close) and Volumes",
    "2. Symbol": "VOO",
    "3. Last Refreshed": "2021-09-22",
    "4. Output Size": "Full size",
    "5. Time Zone": "US/Eastern"
},
"Time Series (Daily)": {
    "2021-09-22": {
        "1. open": "402.1700",
        "2. high": "405.8500",
        "3. low": "401.2600",
        "4. close": "403.9000",
        "5. volume": "5979811"
    },

struct Stock: Codable {
    let metaData: MetaData
    let timeSeriesDaily: [String : TimeSeriesDaily]  // creates a dictionary, key = string : TimeSeriesDaily = value
    enum CodingKeys: String, CodingKey {
        case metaData = "Meta Data"
        case timeSeriesDaily = "Time Series (Daily)"
    }
}
struct MetaData: Codable {
    let Information : String
    let Symbol : String
    let LastRefreshed : String
    let OutputSize : String
    let TimeZone: String
    enum CodingKeys: String, CodingKey {
        case Information = "1. Information"
        case Symbol = "2. Symbol"
        case LastRefreshed = "3. Last Refreshed"
        case OutputSize = "4. Output Size"
        case TimeZone = "5. Time Zone"
    }
}
struct TimeSeriesDaily: Codable {
    let Open, High, Low, 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"
    }
}
class ReadData: ObservableObject  {
    @Published var tmpData = Stock(metaData: ????? , timeSeriesDaily : [:])
    init() {
        loadData()
    }
    func loadData() {
        guard let url = Bundle.main.url(forResource: "VOO", withExtension: "json")
        else {
            print("Json file not found")
            return
        }
        let decoder = JSONDecoder()
        do {
            let data = try Data(contentsOf: url)
            self.tmpData = try decoder.decode(Stock.self, from: data)
//            print(self.tmpData)
        } catch {
            print(error)
        }
    }
}
struct ContentView: View {
    @ObservedObject var vooData = ReadData()
    var body: some View {
        ScrollView  {
            VStack (alignment: .leading) {
                let lastYear = getOneYearAgo()
                let filteredDict = vooData.tmpData.timeSeriesDaily.filter { $0.key > lastYear } // Works
//                let sortedFilteredDict = filteredDict.sorted { $0.key < $1.key }                 // Works
//                let justCloseArray = sortedFilteredDict.map { ($0.key, $0.value.Close) }           // returns array [(String, String)]
//                let justCloseDict = Dictionary(uniqueKeysWithValues: justCloseArray)                // returns dictionary with 1 key & 1 val
//                let sortedCloseDict = justCloseDict.sorted { $0.key < $1.key }                      // works
                let newDict = filteredDict.mapValues { Double($0.Close) }
                let sortedNewDict = newDict.sorted { $0.key < $1.key }
                Spacer()
                //                ForEach ( sortedCloseDict.map { ($0.key, $0.value) }, id: \.0 ) { keyValuePair in
                ForEach ( sortedNewDict.map { ($0.key, $0.value) }, id: \.0 ) { keyValuePair in   // map converts dictionary to arrap
                    HStack {
                        Text (keyValuePair.0)
                        Text ("\(keyValuePair.1!)")
                    }
                }
                Spacer()
            } // end vstack
        } .frame(width: 600, height: 400, alignment: .center) // end scroll view
    }
}

CodePudding user response:

You need to pass a MetaData struct to it. The initializer for MetaData takes a number of Strings that match its properties:

@Published var tmpData = Stock(metaData: MetaData(Information: "", Symbol: "", LastRefreshed: "", OutputSize: "", TimeZone: ""), timeSeriesDaily: [:])

One hint is that Xcode will autocomplete a lot of this for you. If you start typing Stock and let autocomplete do the work, you'll see it generate templates for the metaData and timeSeriesDaily parameters.

  • Related