Reputation: 21
I am currently trying to figure out how to parse JSON information in Python and am having a harder time than I think I should.
Below is a sample of the information I am trying to parse.
{
"2019-05-09": {
"1. open": "124.2900",
"2. high": "125.7800",
"3. low": "123.5700",
"4. close": "125.5000",
"5. volume": "23491093"
},
"2019-05-08": {
"1. open": "125.4400",
"2. high": "126.3700",
"3. low": "124.7500",
"4. close": "125.5100",
"5. volume": "25775583"
},
"2019-05-07": {
"1. open": "126.4600",
"2. high": "127.1800",
"3. low": "124.2200",
"4. close": "125.5200",
"5. volume": "36017661"
}
}
I am trying to store each day into a class so that I can parse the information.
In the below example, I am only trying to print the opening for these records. According to the simple examples I've looked at, this should work but always comes up with the error 'string indices must be integers.'
from alpha_vantage.timeseries import TimeSeries
import json
class day_history:
def __init__(self, date, open, high, low, close, volume):
self.date = date
self.open = open
self.high = high
self.low = low
self.close = close
self.volume = volume
alpha_adv_key = "aaaaaaaaaaa"
ts = TimeSeries(key=alpha_adv_key)
data, meta_data = ts.get_daily(symbol='MSFT')
results = json.dumps(data)
for day in results:
print(day["1. open"])
What is the correct way to parse this JSON data so that I can store it in the class?
Upvotes: 2
Views: 734
Reputation: 7887
If you want to turn it into a class see my code below.
That being said I think the issue you are having is for day in results:
. This is going to return each key (i.e. a string). I think you meant to do for day in results.values():
which will return all the dictionaries.
You can just use the magic of unpacking using **
.
I used your input as a parameter d
.
days = []
for day, info in d.items():
temp = info.copy() # A copy because we don't want to change the original
keys = list(temp.keys()) # List of all keys (Ex: 1. open)
# We want to remove the beginning number so we just have
# the wanted attribute name(Ex: open instead of 1. open)
for key in keys:
temp[key[3:]] = temp.pop(key)
temp['date'] = day # Add our date to the temp dictionary
# note the ** notation. This unpacks a dictionary to keyword arguments
# so it would be like passing: (date=day, open=..., close=..., ...)
# that is why I had to remove the numbers before the variable name.
days.append(day_history(**temp)) # Pass this new dict to our constructor
# This will print out all the days
print(days)
I added a __repr__
method to your class to print them:
def __repr__(self):
return str(self.date) + str(self.high)
If you don't need more class methods you may just want to consider using a namedtuple
:
from collections import namedtuple
Day_History = namedtuple("Day_History", "date open high low close volume")
days = []
for day, info in d.items():
temp = info.copy()
keys = list(temp.keys())
for key in keys:
temp[key[3:]] = temp.pop(key)
temp['date'] = day
days.append(Day_History(**temp))
for day in days:
print(day)
Output:
Day_History(date='2019-05-09', open='124.2900', high='125.7800', low='123.5700', close='125.5000', volume='23491093')
Day_History(date='2019-05-08', open='125.4400', high='126.3700', low='124.7500', close='125.5100', volume='25775583')
Day_History(date='2019-05-07', open='126.4600', high='127.1800', low='124.2200', close='125.5200', volume='36017661')
and you cant print namedtuple
parameters by doing something like:
for day in days:
print(day.open)
Upvotes: 1