pythonjson

How to correctly parse nested JSON output from API call in Python


My goal is, if I understand correctly, to load the entire JSON output in a Python dictionary, for which I should then be able to iterate over, with a for loop, in order to output my selections, in my desired order. I'm trying to print hourly weather, in the format of "current hour" followed by "current temperature". Needs to output 24 rows. The below code I have results in:

time
temperature_2m
precipitation_probability
precipitation
weather_code

but what I really need is the values for these keys, not the keys themselves.

When I try:

print(hour)["time"]

I get:

Traceback (most recent call last):
  File "/home/bthuy/briefing/weather.py", line 40, in <module>
    print(hour["time"])
          ~~~~^^^^^^^^
TypeError: string indices must be integers, not 'str'

I guess I simply do not (yet) understand enough how to use a dictionary, or maybe I am confusing dictionaries and lists in Python and objects and arrays in JSON, I tried following numerous examples but they all fail to get me the desired result: 24 lines output showing the hour and temperature value for this hour.

import requests 
import json 
from datetime import datetime
  
url = "https://api.open-meteo.com/v1/forecast"

params = {
    "latitude": 37.897,
    "longitude": -91.129,
    "hourly": ["temperature_2m", "precipitation_probability", "precipitation", "weather_code"],
    "temperature_unit": "fahrenheit",
    "wind_speed_unit": "mph",
    "precipitation_unit": "inch",
    "forecast_days": 1
}

response = requests.get(url, params)

body_dict = response.json()
#print (body_dict)
#pretty_json = json.dumps(body_dict, indent=4)
#print (pretty_json)

hourly = body_dict["hourly"]
for hour in hourly:
    print (hour)

Here is the contents of body_dict:

{'elevation': 191.0,
 'generationtime_ms': 0.06103515625,
 'hourly': {'precipitation': [0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0,
                              0.0],
            'precipitation_probability': [0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0,
                                          0],
            'temperature_2m': [50.5,
                               49.8,
                               47.9,
                               46.6,
                               45.9,
                               45.3,
                               43.6,
                               43.2,
                               45.3,
                               50.0,
                               54.6,
                               57.7,
                               61.7,
                               63.9,
                               65.7,
                               67.1,
                               66.3,
                               62.7,
                               57.7,
                               54.6,
                               52.5,
                               51.4,
                               50.4,
                               49.2],
            'time': ['2024-11-22T00:00',
                     '2024-11-22T01:00',
                     '2024-11-22T02:00',
                     '2024-11-22T03:00',
                     '2024-11-22T04:00',
                     '2024-11-22T05:00',
                     '2024-11-22T06:00',
                     '2024-11-22T07:00',
                     '2024-11-22T08:00',
                     '2024-11-22T09:00',
                     '2024-11-22T10:00',
                     '2024-11-22T11:00',
                     '2024-11-22T12:00',
                     '2024-11-22T13:00',
                     '2024-11-22T14:00',
                     '2024-11-22T15:00',
                     '2024-11-22T16:00',
                     '2024-11-22T17:00',
                     '2024-11-22T18:00',
                     '2024-11-22T19:00',
                     '2024-11-22T20:00',
                     '2024-11-22T21:00',
                     '2024-11-22T22:00',
                     '2024-11-22T23:00'],
            'weather_code': [0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             0,
                             1,
                             2]},
 'hourly_units': {'precipitation': 'inch',
                  'precipitation_probability': '%',
                  'temperature_2m': '°F',
                  'time': 'iso8601',
                  'weather_code': 'wmo code'},
 'latitude': 37.89382,
 'longitude': -91.12241,
 'timezone': 'America/Chicago',
 'timezone_abbreviation': 'CST',
 'utc_offset_seconds': -21600}

Also, in the meanwhile I found out that I need to add ".values()" in order to get only the values and not the keys:

hourly = body_dict["hourly"]

for hour in hourly.values():
    print (hour)

which outputs both the time and temperature_2m values:

['2024-11-22T00:00', '2024-11-22T01:00', '2024-11-22T02:00', '2024-11-22T03:00', '2024-11-22T04:00', '2024-11-22T05:00', '2024-11-22T06:00', '2024-11-22T07:00', '2024-11-22T08:00', '2024-11-22T09:00', '2024-11-22T10:00', '2024-11-22T11:00', '2024-11-22T12:00', '2024-11-22T13:00', '2024-11-22T14:00', '2024-11-22T15:00', '2024-11-22T16:00', '2024-11-22T17:00', '2024-11-22T18:00', '2024-11-22T19:00', '2024-11-22T20:00', '2024-11-22T21:00', '2024-11-22T22:00', '2024-11-22T23:00']
[50.5, 49.8, 47.9, 46.6, 45.9, 45.3, 43.6, 43.2, 45.3, 50.0, 54.6, 57.7, 61.7, 63.9, 65.7, 67.1, 66.3, 62.7, 57.7, 54.6, 52.5, 51.4, 50.4, 49.2]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3]

What I'm after is to iterate over these again, so the output becomes:

2024-11-22T00:00 50.5
2024-11-22T01:00 49.8

but here is where I'm stuck, I cannot find a way to select both the time and temperature_2m values in a for loop and print them.


Solution

  • Well, first, body_dict is already a dictionary, you don't need any JSON here, after that you can easily access the data with:

    hourly_data = body_dict["hourly"]  
      
    times = hourly_data["time"]  
    temperatures = hourly_data["temperature_2m"]  
      
    for time, temperature in zip(times, temperatures):  
        print(f"{time}: {temperature}°F")  
    

    So, what you are really looking for here is in the hourly_data I added.