Wie man in einem Python-JSON-Objekt auf verschachtelte Schlüssel zugreift

PythonPythonBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Introduction

Python's versatility extends to working with JSON data, a widely-used format for storing and exchanging information. JSON structures can be simple or complex with nested elements, similar to Python dictionaries and lists. In this tutorial, you will learn how to access and extract data from nested JSON structures in Python through practical exercises.

By the end of this lab, you will be able to confidently navigate JSON objects, access deeply nested keys, and work with nested arrays in Python applications.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ControlFlowGroup(["Control Flow"]) python(("Python")) -.-> python/DataStructuresGroup(["Data Structures"]) python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python(("Python")) -.-> python/PythonStandardLibraryGroup(["Python Standard Library"]) python/ControlFlowGroup -.-> python/conditional_statements("Conditional Statements") python/ControlFlowGroup -.-> python/for_loops("For Loops") python/DataStructuresGroup -.-> python/lists("Lists") python/DataStructuresGroup -.-> python/dictionaries("Dictionaries") python/ErrorandExceptionHandlingGroup -.-> python/catching_exceptions("Catching Exceptions") python/PythonStandardLibraryGroup -.-> python/data_collections("Data Collections") python/PythonStandardLibraryGroup -.-> python/data_serialization("Data Serialization") subgraph Lab Skills python/conditional_statements -.-> lab-395034{{"Wie man in einem Python-JSON-Objekt auf verschachtelte Schlüssel zugreift"}} python/for_loops -.-> lab-395034{{"Wie man in einem Python-JSON-Objekt auf verschachtelte Schlüssel zugreift"}} python/lists -.-> lab-395034{{"Wie man in einem Python-JSON-Objekt auf verschachtelte Schlüssel zugreift"}} python/dictionaries -.-> lab-395034{{"Wie man in einem Python-JSON-Objekt auf verschachtelte Schlüssel zugreift"}} python/catching_exceptions -.-> lab-395034{{"Wie man in einem Python-JSON-Objekt auf verschachtelte Schlüssel zugreift"}} python/data_collections -.-> lab-395034{{"Wie man in einem Python-JSON-Objekt auf verschachtelte Schlüssel zugreift"}} python/data_serialization -.-> lab-395034{{"Wie man in einem Python-JSON-Objekt auf verschachtelte Schlüssel zugreift"}} end

Understanding JSON in Python

JSON (JavaScript Object Notation) is a lightweight data-interchange format that is both human-readable and machine-parsable. In Python, JSON objects are represented as dictionaries, and JSON arrays as lists.

Let's start by creating a simple Python script to explore JSON data:

  1. Open the WebIDE and create a new file by clicking on "File > New File" from the menu.

  2. Save the file as basic_json.py in the /home/labex/project/json_practice directory.

  3. Add the following code to basic_json.py:

import json

## A simple JSON object (represented as a Python dictionary)
person = {
    "name": "John Doe",
    "age": 30,
    "email": "[email protected]",
    "is_employed": True,
    "hobbies": ["reading", "hiking", "coding"]
}

## Convert Python dictionary to JSON string
json_string = json.dumps(person, indent=2)
print("JSON as string:")
print(json_string)
print("\n" + "-" * 50 + "\n")

## Convert JSON string back to Python dictionary
parsed_json = json.loads(json_string)
print("Python dictionary:")
print(parsed_json)
print("\n" + "-" * 50 + "\n")

## Accessing basic elements
print("Basic access examples:")
print(f"Name: {parsed_json['name']}")
print(f"Age: {parsed_json['age']}")
print(f"First hobby: {parsed_json['hobbies'][0]}")
  1. Run the script by opening a terminal in WebIDE and executing:
cd /home/labex/project/json_practice
python3 basic_json.py

You should see the following output:

JSON as string:
{
  "name": "John Doe",
  "age": 30,
  "email": "[email protected]",
  "is_employed": true,
  "hobbies": [
    "reading",
    "hiking",
    "coding"
  ]
}

--------------------------------------------------

Python dictionary:
{'name': 'John Doe', 'age': 30, 'email': '[email protected]', 'is_employed': True, 'hobbies': ['reading', 'hiking', 'coding']}

--------------------------------------------------

Basic access examples:
Name: John Doe
Age: 30
First hobby: reading

Understanding the Code

  • json.dumps() converts a Python object to a JSON formatted string
  • json.loads() parses a JSON string and converts it to a Python object
  • To access elements in a JSON object, use the dictionary syntax: object_name['key']
  • To access elements in a JSON array, use list indexing: array_name[index]

This example demonstrates the basic operations for working with JSON in Python. In the next step, we will explore how to access nested JSON structures.

Accessing Nested Dictionary Keys

JSON objects often contain nested structures. In Python, we can access nested data using multiple square brackets or by chaining dictionary keys.

Let's create a new script to explore nested JSON objects:

  1. In the WebIDE, create a new file and save it as nested_dict.py in the /home/labex/project/json_practice directory.

  2. Add the following code to nested_dict.py:

import json

## JSON with nested object
user_data = {
    "name": "John Doe",
    "age": 30,
    "contact": {
        "email": "[email protected]",
        "phone": "555-1234",
        "address": {
            "street": "123 Main St",
            "city": "Anytown",
            "state": "CA",
            "zip": "12345"
        }
    },
    "preferences": {
        "theme": "dark",
        "notifications": True
    }
}

## Let's prettify and print the JSON structure
print("Full JSON structure:")
print(json.dumps(user_data, indent=2))
print("\n" + "-" * 50 + "\n")

## Accessing nested elements
print("Accessing nested elements:")
print(f"Email: {user_data['contact']['email']}")
print(f"City: {user_data['contact']['address']['city']}")
print(f"Theme: {user_data['preferences']['theme']}")
print("\n" + "-" * 50 + "\n")

## Safe access with get() method
print("Safe access with get():")
## get() returns None if key doesn't exist, or a default value if specified
phone = user_data.get('contact', {}).get('phone', 'Not available')
country = user_data.get('contact', {}).get('address', {}).get('country', 'Not specified')

print(f"Phone: {phone}")
print(f"Country: {country}")  ## This key doesn't exist but won't cause an error
  1. Run the script in the terminal:
cd /home/labex/project/json_practice
python3 nested_dict.py

You should see output similar to:

Full JSON structure:
{
  "name": "John Doe",
  "age": 30,
  "contact": {
    "email": "[email protected]",
    "phone": "555-1234",
    "address": {
      "street": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "zip": "12345"
    }
  },
  "preferences": {
    "theme": "dark",
    "notifications": true
  }
}

--------------------------------------------------

Accessing nested elements:
Email: [email protected]
City: Anytown
Theme: dark

--------------------------------------------------

Safe access with get():
Phone: 555-1234
Country: Not specified

Understanding Nested Access

When working with nested JSON structures, you can access nested elements by chaining keys with square brackets:

## Syntax for nested access
value = json_data['key1']['key2']['key3']

However, this approach can cause errors if any key in the chain doesn't exist. The safer method is to use the get() function, which allows you to provide a default value if a key is missing:

## Safe access with get() method
value = json_data.get('key1', {}).get('key2', {}).get('key3', 'default_value')

This safe access pattern is particularly valuable when working with API responses or other external JSON data where the structure might not be consistent.

Working with Nested Arrays in JSON

JSON data often includes arrays (lists in Python) that might contain other objects or arrays. Let's explore how to access elements within nested arrays.

  1. In the WebIDE, create a new file and save it as nested_arrays.py in the /home/labex/project/json_practice directory.

  2. Add the following code to nested_arrays.py:

import json

## JSON with nested arrays
company_data = {
    "name": "Tech Innovations Inc",
    "founded": 2010,
    "departments": [
        {
            "name": "Engineering",
            "employees": [
                {"name": "Alice Johnson", "role": "Software Engineer", "skills": ["Python", "JavaScript", "AWS"]},
                {"name": "Bob Smith", "role": "DevOps Engineer", "skills": ["Docker", "Kubernetes", "Linux"]}
            ]
        },
        {
            "name": "Marketing",
            "employees": [
                {"name": "Carol Williams", "role": "Marketing Manager", "skills": ["SEO", "Content Strategy"]},
                {"name": "Dave Brown", "role": "Social Media Specialist", "skills": ["Facebook Ads", "Instagram"]}
            ]
        }
    ],
    "locations": ["San Francisco", "New York", "London"]
}

## Print the JSON structure
print("Company Data:")
print(json.dumps(company_data, indent=2))
print("\n" + "-" * 50 + "\n")

## Accessing elements in arrays
print("Accessing array elements:")
print(f"First location: {company_data['locations'][0]}")
print(f"Number of departments: {len(company_data['departments'])}")
print(f"First department name: {company_data['departments'][0]['name']}")
print("\n" + "-" * 50 + "\n")

## Iterating through nested arrays
print("All employees and their skills:")
for department in company_data['departments']:
    dept_name = department['name']
    print(f"\nDepartment: {dept_name}")
    print("-" * 20)

    for employee in department['employees']:
        print(f"  {employee['name']} ({employee['role']})")
        print(f"  Skills: {', '.join(employee['skills'])}")
        print()

## Finding specific data in nested arrays
print("-" * 50 + "\n")
print("Finding employees with Python skills:")

for department in company_data['departments']:
    for employee in department['employees']:
        if "Python" in employee['skills']:
            print(f"  {employee['name']} in {department['name']} department")
  1. Run the script in the terminal:
cd /home/labex/project/json_practice
python3 nested_arrays.py

You should see output similar to:

Company Data:
{
  "name": "Tech Innovations Inc",
  "founded": 2010,
  "departments": [
    {
      "name": "Engineering",
      "employees": [
        {
          "name": "Alice Johnson",
          "role": "Software Engineer",
          "skills": [
            "Python",
            "JavaScript",
            "AWS"
          ]
        },
        {
          "name": "Bob Smith",
          "role": "DevOps Engineer",
          "skills": [
            "Docker",
            "Kubernetes",
            "Linux"
          ]
        }
      ]
    },
    {
      "name": "Marketing",
      "employees": [
        {
          "name": "Carol Williams",
          "role": "Marketing Manager",
          "skills": [
            "SEO",
            "Content Strategy"
          ]
        },
        {
          "name": "Dave Brown",
          "role": "Social Media Specialist",
          "skills": [
            "Facebook Ads",
            "Instagram"
          ]
        }
      ]
    }
  ],
  "locations": [
    "San Francisco",
    "New York",
    "London"
  ]
}

--------------------------------------------------

Accessing array elements:
First location: San Francisco
Number of departments: 2
First department name: Engineering

--------------------------------------------------

All employees and their skills:

Department: Engineering
--------------------
  Alice Johnson (Software Engineer)
  Skills: Python, JavaScript, AWS

  Bob Smith (DevOps Engineer)
  Skills: Docker, Kubernetes, Linux


Department: Marketing
--------------------
  Carol Williams (Marketing Manager)
  Skills: SEO, Content Strategy

  Dave Brown (Social Media Specialist)
  Skills: Facebook Ads, Instagram

--------------------------------------------------

Finding employees with Python skills:
  Alice Johnson in Engineering department

Understanding Nested Array Access

Working with nested arrays in JSON involves a combination of:

  1. Indexed access: Use square brackets with an index to access specific array elements (array[0])
  2. Nested property access: Chain dictionary keys and array indices (data['departments'][0]['employees'])
  3. Iteration: Use loops to process multiple items in arrays

The most common pattern for working with nested arrays is to use nested for loops:

for outer_item in json_data['outer_array']:
    for inner_item in outer_item['inner_array']:
        ## Process the inner_item
        print(inner_item['property'])

This approach allows you to traverse complex nested structures and extract the specific data you need.

Handling Missing Keys and Error Prevention

When working with complex JSON structures, especially from external sources like APIs, it's important to handle potential errors that arise when keys are missing. Let's explore techniques to safely access nested JSON data.

  1. In the WebIDE, create a new file and save it as error_handling.py in the /home/labex/project/json_practice directory.

  2. Add the following code to error_handling.py:

import json

## JSON with inconsistent structure
api_response = {
    "status": "success",
    "data": {
        "users": [
            {
                "id": 1,
                "name": "John Doe",
                "contact": {
                    "email": "[email protected]",
                    "phone": "555-1234"
                },
                "roles": ["admin", "user"]
            },
            {
                "id": 2,
                "name": "Jane Smith",
                ## Missing contact info
                "roles": ["user"]
            },
            {
                "id": 3,
                "name": "Bob Johnson",
                "contact": {
                    ## Only has email, no phone
                    "email": "[email protected]"
                }
                ## Missing roles
            }
        ]
    }
}

print("API Response Structure:")
print(json.dumps(api_response, indent=2))
print("\n" + "-" * 50 + "\n")

## Approach 1: Using try-except blocks
print("Method 1: Using try-except blocks")
print("-" * 30)

for user in api_response["data"]["users"]:
    print(f"User: {user['name']}")

    ## Get email
    try:
        email = user['contact']['email']
        print(f"  Email: {email}")
    except (KeyError, TypeError):
        print("  Email: Not available")

    ## Get phone
    try:
        phone = user['contact']['phone']
        print(f"  Phone: {phone}")
    except (KeyError, TypeError):
        print("  Phone: Not available")

    ## Get roles
    try:
        roles = ", ".join(user['roles'])
        print(f"  Roles: {roles}")
    except (KeyError, TypeError):
        print("  Roles: None assigned")

    print()

## Approach 2: Using get() method with defaults
print("\n" + "-" * 50 + "\n")
print("Method 2: Using get() method with defaults")
print("-" * 30)

for user in api_response["data"]["users"]:
    print(f"User: {user['name']}")

    ## Get contact info with nested get() calls
    contact = user.get('contact', {})
    email = contact.get('email', 'Not available')
    phone = contact.get('phone', 'Not available')

    print(f"  Email: {email}")
    print(f"  Phone: {phone}")

    ## Get roles with default empty list
    roles = user.get('roles', [])
    roles_str = ", ".join(roles) if roles else "None assigned"
    print(f"  Roles: {roles_str}")

    print()
  1. Run the script in the terminal:
cd /home/labex/project/json_practice
python3 error_handling.py

You should see output similar to:

API Response Structure:
{
  "status": "success",
  "data": {
    "users": [
      {
        "id": 1,
        "name": "John Doe",
        "contact": {
          "email": "[email protected]",
          "phone": "555-1234"
        },
        "roles": [
          "admin",
          "user"
        ]
      },
      {
        "id": 2,
        "name": "Jane Smith",
        "roles": [
          "user"
        ]
      },
      {
        "id": 3,
        "name": "Bob Johnson",
        "contact": {
          "email": "[email protected]"
        }
      }
    ]
  }
}

--------------------------------------------------

Method 1: Using try-except blocks
------------------------------
User: John Doe
  Email: [email protected]
  Phone: 555-1234
  Roles: admin, user

User: Jane Smith
  Email: Not available
  Phone: Not available
  Roles: user

User: Bob Johnson
  Email: [email protected]
  Phone: Not available
  Roles: None assigned


--------------------------------------------------

Method 2: Using get() method with defaults
------------------------------
User: John Doe
  Email: [email protected]
  Phone: 555-1234
  Roles: admin, user

User: Jane Smith
  Email: Not available
  Phone: Not available
  Roles: user

User: Bob Johnson
  Email: [email protected]
  Phone: Not available
  Roles: None assigned

Understanding Error Handling Techniques

The example demonstrates two main approaches for safely accessing nested JSON data:

  1. Try-Except Blocks

    • Wrap potentially risky access in try-except blocks
    • Catch KeyError (missing dictionary key) and TypeError (attempting to access a key on a non-dictionary)
    • Provide fallback values when errors occur
  2. Chained get() Method

    • Use the dictionary get() method which takes a default value as its second argument
    • Chain multiple get() calls for nested structures
    • Provides cleaner code without exception handling

The get() method approach is generally preferred for its readability and conciseness when dealing with nested JSON structures. It allows you to provide default values at each level of nesting.

## Safe nested access pattern
value = data.get('level1', {}).get('level2', {}).get('level3', 'default_value')

Using these error handling techniques will make your code more robust when working with JSON data from various sources.

Practical Exercise: Building a JSON Data Extractor

Let's put your knowledge into practice by creating a program that extracts specific information from a complex JSON structure. This could represent a real-world scenario where you receive JSON data from an API and need to process it.

  1. In the WebIDE, create a new file and save it as json_extractor.py in the /home/labex/project/json_practice directory.

  2. Add the following code to json_extractor.py:

import json

## A complex nested JSON structure (e.g., from a weather API)
weather_data = {
    "location": {
        "name": "New York",
        "region": "New York",
        "country": "United States of America",
        "lat": 40.71,
        "lon": -74.01,
        "timezone": "America/New_York"
    },
    "current": {
        "temp_c": 22.0,
        "temp_f": 71.6,
        "condition": {
            "text": "Partly cloudy",
            "icon": "//cdn.weatherapi.com/weather/64x64/day/116.png",
            "code": 1003
        },
        "wind_mph": 6.9,
        "wind_kph": 11.2,
        "wind_dir": "ENE",
        "humidity": 65,
        "cloud": 75,
        "feelslike_c": 22.0,
        "feelslike_f": 71.6
    },
    "forecast": {
        "forecastday": [
            {
                "date": "2023-09-20",
                "day": {
                    "maxtemp_c": 24.3,
                    "maxtemp_f": 75.7,
                    "mintemp_c": 18.6,
                    "mintemp_f": 65.5,
                    "condition": {
                        "text": "Patchy rain possible",
                        "icon": "//cdn.weatherapi.com/weather/64x64/day/176.png",
                        "code": 1063
                    },
                    "daily_chance_of_rain": 85
                },
                "astro": {
                    "sunrise": "06:41 AM",
                    "sunset": "07:01 PM",
                    "moonrise": "10:15 AM",
                    "moonset": "08:52 PM"
                },
                "hour": [
                    {
                        "time": "2023-09-20 00:00",
                        "temp_c": 20.1,
                        "condition": {
                            "text": "Clear",
                            "icon": "//cdn.weatherapi.com/weather/64x64/night/113.png",
                            "code": 1000
                        },
                        "chance_of_rain": 0
                    },
                    {
                        "time": "2023-09-20 12:00",
                        "temp_c": 23.9,
                        "condition": {
                            "text": "Overcast",
                            "icon": "//cdn.weatherapi.com/weather/64x64/day/122.png",
                            "code": 1009
                        },
                        "chance_of_rain": 20
                    }
                ]
            },
            {
                "date": "2023-09-21",
                "day": {
                    "maxtemp_c": 21.2,
                    "maxtemp_f": 70.2,
                    "mintemp_c": 16.7,
                    "mintemp_f": 62.1,
                    "condition": {
                        "text": "Heavy rain",
                        "icon": "//cdn.weatherapi.com/weather/64x64/day/308.png",
                        "code": 1195
                    },
                    "daily_chance_of_rain": 92
                },
                "astro": {
                    "sunrise": "06:42 AM",
                    "sunset": "06:59 PM",
                    "moonrise": "11:30 AM",
                    "moonset": "09:15 PM"
                }
            }
        ]
    }
}

def extract_weather_summary(data):
    """
    Extract and format a weather summary from the provided data.
    """
    try:
        ## Location information
        location = data.get("location", {})
        location_name = location.get("name", "Unknown")
        country = location.get("country", "Unknown")

        ## Current weather
        current = data.get("current", {})
        temp_c = current.get("temp_c", "N/A")
        temp_f = current.get("temp_f", "N/A")
        condition = current.get("condition", {}).get("text", "Unknown")
        humidity = current.get("humidity", "N/A")

        ## Forecast
        forecast_days = data.get("forecast", {}).get("forecastday", [])

        ## Build summary string
        summary = f"Weather Summary for {location_name}, {country}\n"
        summary += f"==================================================\n\n"
        summary += f"Current Conditions:\n"
        summary += f"  Temperature: {temp_c}°C ({temp_f}°F)\n"
        summary += f"  Condition: {condition}\n"
        summary += f"  Humidity: {humidity}%\n\n"

        if forecast_days:
            summary += "Forecast:\n"
            for day_data in forecast_days:
                date = day_data.get("date", "Unknown date")
                day = day_data.get("day", {})
                max_temp = day.get("maxtemp_c", "N/A")
                min_temp = day.get("mintemp_c", "N/A")
                condition = day.get("condition", {}).get("text", "Unknown")
                rain_chance = day.get("daily_chance_of_rain", "N/A")

                summary += f"  {date}:\n"
                summary += f"    High: {max_temp}°C, Low: {min_temp}°C\n"
                summary += f"    Condition: {condition}\n"
                summary += f"    Chance of Rain: {rain_chance}%\n"

                ## Get sunrise and sunset times if available
                astro = day_data.get("astro", {})
                if astro:
                    sunrise = astro.get("sunrise", "N/A")
                    sunset = astro.get("sunset", "N/A")
                    summary += f"    Sunrise: {sunrise}, Sunset: {sunset}\n"

                summary += "\n"

        return summary

    except Exception as e:
        return f"Error extracting weather data: {str(e)}"

## Print the full JSON data
print("Original Weather Data:")
print(json.dumps(weather_data, indent=2))
print("\n" + "-" * 60 + "\n")

## Extract and print the weather summary
weather_summary = extract_weather_summary(weather_data)
print(weather_summary)

## Save the summary to a file
with open("weather_summary.txt", "w") as file:
    file.write(weather_summary)

print("\nWeather summary has been saved to 'weather_summary.txt'")
  1. Run the script in the terminal:
cd /home/labex/project/json_practice
python3 json_extractor.py
  1. After running the script, you can view the generated summary file:
cat weather_summary.txt

You'll see the formatted weather summary extracted from the complex JSON structure.

Understanding the JSON Extractor

This practical exercise demonstrates several important concepts for working with nested JSON data:

  1. Safe data extraction

    • Using the get() method with default values to handle missing keys
    • Accessing nested data with chained get() calls
    • Error handling with try-except blocks
  2. Data transformation

    • Converting JSON data into a human-readable format
    • Iterating through nested arrays to process multiple items
    • Extracting only the relevant information from a complex structure
  3. Defensive programming

    • Anticipating and handling potential issues
    • Providing default values when data is missing
    • Catching exceptions to prevent program crashes

This pattern of extracting, transforming, and presenting JSON data is common in many real-world applications, such as:

  • Processing API responses
  • Generating reports from data
  • Filtering and displaying information for users

By following these patterns, you can reliably work with JSON data of any complexity.

Summary

In this lab, you have learned how to work with nested JSON structures in Python:

  1. Basic JSON handling - Converting between Python objects and JSON strings using json.dumps() and json.loads().

  2. Accessing nested dictionary keys - Using chained square bracket notation to access deeply nested values in JSON objects.

  3. Working with nested arrays - Navigating and extracting data from arrays within JSON structures using indexing and iteration.

  4. Error handling techniques - Implementing safe access patterns with try-except blocks and the get() method to handle missing keys.

  5. Practical data extraction - Building a complete application that extracts, transforms, and presents data from a complex JSON structure.

These skills are essential for working with data from APIs, configuration files, and other data exchange scenarios. You now have the foundation to confidently handle JSON data of any complexity in your Python applications.

For further learning, consider exploring:

  • Working with real APIs that return JSON data
  • Using libraries like pandas to analyze JSON data
  • Implementing JSON validation with jsonschema
  • Creating and manipulating custom JSON structures