简体   繁体   中英

Iterate through multi level json/dictionaries in Python 3

I am fetching data from an api

data = json.loads(api_response.content)

which returns

{
  'NKE': {
    'quote': {
      'symbol': 'NKE',
      'companyName': 'NIKE, Inc.',
      'primaryExchange': 'New York Stock Exchange',
      'calculationPrice': 'close',
      'open': 101.14,
      'openTime': 1578321000670,
      'close': 101.83,
      'closeTime': 1578344409251,
      'high': 101.84,
      'low': 100.869,
      'latestPrice': 101.83,
      'latestSource': 'Close',
      'latestTime': 'January 6, 2020',
      'latestUpdate': 1578344409251,
      'latestVolume': 4608458,
      'iexRealtimePrice': 0,
      'iexRealtimeSize': 0,
      'iexLastUpdated': 0,
      'delayedPrice': 101.83,
      'delayedPriceTime': 1578346947002,
      'extendedPrice': 101.99,
      'extendedChange': 0.16,
      'extendedChangePercent': 0.00157,
      'extendedPriceTime': 1578400716493,
      'previousClose': 101.92,
      'previousVolume': 4542003,
      'change': -0.09,
      'changePercent': -0.00088,
      'volume': 0,
      'iexMarketPercent': None,
      'iexVolume': 0,
      'avgTotalVolume': 5776147,
      'iexBidPrice': 0,
      'iexBidSize': 0,
      'iexAskPrice': 0,
      'iexAskSize': 0,
      'marketCap': 158959684900,
      'peRatio': 34.88,
      'week52High': 102.21,
      'week52Low': 74.3,
      'ytdChange': -0.0045,
      'lastTradeTime': 1578344409241,
      'isUSMarketOpen': False
    }
  },
  'UAA': {
    'quote': {
      'symbol': 'UAA',
      'companyName': 'Under Armour, Inc.',
      'primaryExchange': 'New York Stock Exchange',
      'calculationPrice': 'close',
      'open': 21.51,
      'openTime': 1578321000404,
      'close': 20.44,
      'closeTime': 1578344686271,
      'high': 21.53,
      'low': 20.35,
      'latestPrice': 20.44,
      'latestSource': 'Close',
      'latestTime': 'January 6, 2020',
      'latestUpdate': 1578344686271,
      'latestVolume': 11132892,
      'iexRealtimePrice': 0,
      'iexRealtimeSize': 0,
      'iexLastUpdated': 0,
      'delayedPrice': 20.49,
      'delayedPriceTime': 1578347272279,
      'extendedPrice': 0,
      'extendedChange': None,
      'extendedChangePercent': None,
      'extendedPriceTime': 1578356330039,
      'previousClose': 21.85,
      'previousVolume': 4596587,
      'change': -1.41,
      'changePercent': -0.06453,
      'volume': 0,
      'iexMarketPercent': None,
      'iexVolume': 0,
      'avgTotalVolume': 4329339,
      'iexBidPrice': 0,
      'iexBidSize': 0,
      'iexAskPrice': 0,
      'iexAskSize': 0,
      'marketCap': 9230009040,
      'peRatio': 82.55,
      'week52High': 27.72,
      'week52Low': 16.74,
      'ytdChange': -0.126054,
      'lastTradeTime': 1578344399983,
      'isUSMarketOpen': False
    }
  },

my aim is to access elements on the third and final level like symbol, companyName and latestPrice and add it to a database

dic_data = {
            "symbol": data['symbol'] , 
            "latestPrice": data['latestPrice'] , 
            "companyName":  data['companyName'], 
            "week52High": data['week52High'] , 
            "week52Low": data['week52Low'] , 
            "ytdChange": data['ytdChange'] ,
            "latestTime":  data['latestTime'],  
            "changePercent": data['changePercent'] , 
            }
)

how can I loop through data and access the last level of the dictionary?

For looping through all quote dictionaries do:

for key in data:
    data_quote = data[key]['quote']
    for quote_key in data_quote:
        # Do your stuff with data_quote[quote_key]

Try this:

li = []
for i in data:
    for j in data[i]:
        li.append({'symbol': data[i][j]['symbol'], "latestPrice": data[i][j]['latestPrice']})
print(li)

This will get you the output:

output = [
    {
        "symbol": data[company]['quote']['symbol'],
        "latestPrice": data[company]['quote']['latestPrice'],
        "companyName": data[company]['quote']['companyName'],
        "week52High": data[company]['quote']['week52High'],
        "week52Low": data[company]['quote']['week52Low'],
        "ytdChange": data[company]['quote']['ytdChange'],
        "latestTime": data[company]['quote']['latestTime'],
        "changePercent": data[company]['quote']['changePercent'],
    } for company in data
]

Nice answers have already been posted. I am just posting a recursive method. This is just to bring out the variety of ways it can be solved.

Please be warned about cautions raised against Recursive methods everywhere. However recursion is a nice method if you don't know beforehand how many for loops are needed to solve the problem

My code is as below. I have assumed that data is the name of the nested dictionary that you have. ReturnedDict is the name of the dictionary that you finally want.

from collections import defaultdict
LookUpList = ['symbol' , 'latestPrice','companyName', 'week52High' , 'week52Low' , 'ytdChange' ,'latestTime', 'changePercent']
ReturnedDict = defaultdict(list)

def ReachALevelAndGrabValue(DictionaryToAssess):
    for everyKey in DictionaryToAssess:
        if isinstance(DictionaryToAssess[everyKey], dict):
            ReachALevelAndGrabValue(DictionaryToAssess[everyKey])
        else:
            if everyKey in LookUpList:
                ReturnedDict[everyKey].append(DictionaryToAssess[everyKey])


ReachALevelAndGrabValue(data)
print(ReturnedDict)

This gives me the printout as below.

defaultdict(<class 'list'>, {'symbol': ['NKE', 'UAA'], 'companyName': ['NIKE, Inc.', 'Under Armour, Inc.'], 'latestPrice': [101.83, 20.44], 'latestTime': ['January 6, 2020', 'January 6, 2020'], 'changePercent': [-0.00088, -0.06453], 'week52High': [102.21, 27.72], 'week52Low': [74.3, 16.74], 'ytdChange': [-0.0045, -0.126054]})

Is this what you wanted?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM