Introdução
A versatilidade do Python estende-se ao trabalho com dados JSON, um formato amplamente utilizado para armazenar e trocar informações. As estruturas JSON podem ser simples ou complexas, com elementos aninhados, semelhantes aos dicionários e listas do Python. Neste tutorial, você aprenderá como acessar e extrair dados de estruturas JSON aninhadas em Python através de exercícios práticos.
Ao final deste laboratório, você será capaz de navegar com confiança em objetos JSON, acessar chaves profundamente aninhadas e trabalhar com arrays aninhados em aplicações Python.
Compreendendo JSON em Python
JSON (JavaScript Object Notation) é um formato leve de intercâmbio de dados que é legível por humanos e analisável por máquinas. Em Python, objetos JSON são representados como dicionários, e arrays JSON como listas.
Vamos começar criando um script Python simples para explorar dados JSON:
Abra o WebIDE e crie um novo arquivo clicando em "File > New File" no menu.
Salve o arquivo como
basic_json.pyno diretório/home/labex/project/json_practice.Adicione o seguinte código a
basic_json.py:
import json
## A simple JSON object (represented as a Python dictionary)
person = {
"name": "John Doe",
"age": 30,
"email": "john.doe@example.com",
"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]}")
- Execute o script abrindo um terminal no WebIDE e executando:
cd /home/labex/project/json_practice
python3 basic_json.py
Você deve ver a seguinte saída:
JSON as string:
{
"name": "John Doe",
"age": 30,
"email": "john.doe@example.com",
"is_employed": true,
"hobbies": [
"reading",
"hiking",
"coding"
]
}
--------------------------------------------------
Python dictionary:
{'name': 'John Doe', 'age': 30, 'email': 'john.doe@example.com', 'is_employed': True, 'hobbies': ['reading', 'hiking', 'coding']}
--------------------------------------------------
Basic access examples:
Name: John Doe
Age: 30
First hobby: reading
Entendendo o Código
json.dumps()converte um objeto Python em uma string formatada em JSONjson.loads()analisa uma string JSON e a converte em um objeto Python- Para acessar elementos em um objeto JSON, use a sintaxe do dicionário:
nome_do_objeto['chave'] - Para acessar elementos em um array JSON, use a indexação de lista:
nome_do_array[índice]
Este exemplo demonstra as operações básicas para trabalhar com JSON em Python. No próximo passo, exploraremos como acessar estruturas JSON aninhadas.
Acessando Chaves de Dicionários Aninhados
Objetos JSON frequentemente contêm estruturas aninhadas. Em Python, podemos acessar dados aninhados usando múltiplos colchetes ou encadeando chaves de dicionário.
Vamos criar um novo script para explorar objetos JSON aninhados:
No WebIDE, crie um novo arquivo e salve-o como
nested_dict.pyno diretório/home/labex/project/json_practice.Adicione o seguinte código a
nested_dict.py:
import json
## JSON with nested object
user_data = {
"name": "John Doe",
"age": 30,
"contact": {
"email": "john.doe@example.com",
"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
- Execute o script no terminal:
cd /home/labex/project/json_practice
python3 nested_dict.py
Você deve ver uma saída semelhante a:
Full JSON structure:
{
"name": "John Doe",
"age": 30,
"contact": {
"email": "john.doe@example.com",
"phone": "555-1234",
"address": {
"street": "123 Main St",
"city": "Anytown",
"state": "CA",
"zip": "12345"
}
},
"preferences": {
"theme": "dark",
"notifications": true
}
}
--------------------------------------------------
Accessing nested elements:
Email: john.doe@example.com
City: Anytown
Theme: dark
--------------------------------------------------
Safe access with get():
Phone: 555-1234
Country: Not specified
Compreendendo o Acesso Aninhado
Ao trabalhar com estruturas JSON aninhadas, você pode acessar elementos aninhados encadeando chaves com colchetes:
## Syntax for nested access
value = json_data['key1']['key2']['key3']
No entanto, essa abordagem pode causar erros se alguma chave na cadeia não existir. O método mais seguro é usar a função get(), que permite fornecer um valor padrão se uma chave estiver ausente:
## Safe access with get() method
value = json_data.get('key1', {}).get('key2', {}).get('key3', 'default_value')
Este padrão de acesso seguro é particularmente valioso ao trabalhar com respostas de API ou outros dados JSON externos, onde a estrutura pode não ser consistente.
Trabalhando com Arrays Aninhados em JSON
Dados JSON frequentemente incluem arrays (listas em Python) que podem conter outros objetos ou arrays. Vamos explorar como acessar elementos dentro de arrays aninhados.
No WebIDE, crie um novo arquivo e salve-o como
nested_arrays.pyno diretório/home/labex/project/json_practice.Adicione o seguinte código a
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")
- Execute o script no terminal:
cd /home/labex/project/json_practice
python3 nested_arrays.py
Você deve ver uma saída semelhante a:
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
Compreendendo o Acesso a Arrays Aninhados
Trabalhar com arrays aninhados em JSON envolve uma combinação de:
- Acesso indexado: Use colchetes com um índice para acessar elementos específicos do array (
array[0]) - Acesso a propriedades aninhadas: Encadeie chaves de dicionário e índices de array (
data['departments'][0]['employees']) - Iteração: Use loops para processar múltiplos itens em arrays
O padrão mais comum para trabalhar com arrays aninhados é usar loops for aninhados:
for outer_item in json_data['outer_array']:
for inner_item in outer_item['inner_array']:
## Process the inner_item
print(inner_item['property'])
Essa abordagem permite que você percorra estruturas aninhadas complexas e extraia os dados específicos que você precisa.
Lidando com Chaves Ausentes e Prevenção de Erros
Ao trabalhar com estruturas JSON complexas, especialmente de fontes externas como APIs, é importante lidar com potenciais erros que surgem quando chaves estão ausentes. Vamos explorar técnicas para acessar com segurança dados JSON aninhados.
No WebIDE, crie um novo arquivo e salve-o como
error_handling.pyno diretório/home/labex/project/json_practice.Adicione o seguinte código a
error_handling.py:
import json
## JSON with inconsistent structure
api_response = {
"status": "success",
"data": {
"users": [
{
"id": 1,
"name": "John Doe",
"contact": {
"email": "john.doe@example.com",
"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": "bob.johnson@example.com"
}
## 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()
- Execute o script no terminal:
cd /home/labex/project/json_practice
python3 error_handling.py
Você deve ver uma saída semelhante a:
API Response Structure:
{
"status": "success",
"data": {
"users": [
{
"id": 1,
"name": "John Doe",
"contact": {
"email": "john.doe@example.com",
"phone": "555-1234"
},
"roles": [
"admin",
"user"
]
},
{
"id": 2,
"name": "Jane Smith",
"roles": [
"user"
]
},
{
"id": 3,
"name": "Bob Johnson",
"contact": {
"email": "bob.johnson@example.com"
}
}
]
}
}
--------------------------------------------------
Method 1: Using try-except blocks
------------------------------
User: John Doe
Email: john.doe@example.com
Phone: 555-1234
Roles: admin, user
User: Jane Smith
Email: Not available
Phone: Not available
Roles: user
User: Bob Johnson
Email: bob.johnson@example.com
Phone: Not available
Roles: None assigned
--------------------------------------------------
Method 2: Using get() method with defaults
------------------------------
User: John Doe
Email: john.doe@example.com
Phone: 555-1234
Roles: admin, user
User: Jane Smith
Email: Not available
Phone: Not available
Roles: user
User: Bob Johnson
Email: bob.johnson@example.com
Phone: Not available
Roles: None assigned
Compreendendo as Técnicas de Tratamento de Erros
O exemplo demonstra duas abordagens principais para acessar com segurança dados JSON aninhados:
Blocos Try-Except
- Envolva o acesso potencialmente arriscado em blocos try-except
- Capture KeyError (chave de dicionário ausente) e TypeError (tentativa de acessar uma chave em um não-dicionário)
- Forneça valores de fallback quando ocorrem erros
Método get() Encadeado
- Use o método get() do dicionário, que recebe um valor padrão como seu segundo argumento
- Encadeie múltiplas chamadas get() para estruturas aninhadas
- Fornece um código mais limpo sem tratamento de exceção
A abordagem do método get() é geralmente preferida por sua legibilidade e concisão ao lidar com estruturas JSON aninhadas. Ele permite que você forneça valores padrão em cada nível de aninhamento.
## Safe nested access pattern
value = data.get('level1', {}).get('level2', {}).get('level3', 'default_value')
Usar essas técnicas de tratamento de erros tornará seu código mais robusto ao trabalhar com dados JSON de várias fontes.
Exercício Prático: Construindo um Extrator de Dados JSON
Vamos colocar seu conhecimento em prática criando um programa que extrai informações específicas de uma estrutura JSON complexa. Isso pode representar um cenário do mundo real em que você recebe dados JSON de uma API e precisa processá-los.
No WebIDE, crie um novo arquivo e salve-o como
json_extractor.pyno diretório/home/labex/project/json_practice.Adicione o seguinte código a
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'")
- Execute o script no terminal:
cd /home/labex/project/json_practice
python3 json_extractor.py
- Após executar o script, você pode visualizar o arquivo de resumo gerado:
cat weather_summary.txt
Você verá o resumo do tempo formatado extraído da estrutura JSON complexa.
Compreendendo o Extrator JSON
Este exercício prático demonstra vários conceitos importantes para trabalhar com dados JSON aninhados:
Extração segura de dados
- Usando o método
get()com valores padrão para lidar com chaves ausentes - Acessando dados aninhados com chamadas
get()encadeadas - Tratamento de erros com blocos try-except
- Usando o método
Transformação de dados
- Convertendo dados JSON em um formato legível por humanos
- Iterando por arrays aninhados para processar vários itens
- Extraindo apenas as informações relevantes de uma estrutura complexa
Programação defensiva
- Antecipando e lidando com possíveis problemas
- Fornecendo valores padrão quando os dados estão ausentes
- Capturando exceções para evitar falhas no programa
Este padrão de extração, transformação e apresentação de dados JSON é comum em muitas aplicações do mundo real, como:
- Processamento de respostas de API
- Geração de relatórios a partir de dados
- Filtragem e exibição de informações para usuários
Seguindo esses padrões, você pode trabalhar de forma confiável com dados JSON de qualquer complexidade.
Resumo
Neste laboratório, você aprendeu a trabalhar com estruturas JSON aninhadas em Python:
Manipulação básica de JSON - Convertendo entre objetos Python e strings JSON usando
json.dumps()ejson.loads().Acessando chaves de dicionário aninhadas - Usando a notação de colchetes encadeados para acessar valores profundamente aninhados em objetos JSON.
Trabalhando com arrays aninhados - Navegando e extraindo dados de arrays dentro de estruturas JSON usando indexação e iteração.
Técnicas de tratamento de erros - Implementando padrões de acesso seguro com blocos try-except e o método
get()para lidar com chaves ausentes.Extração prática de dados - Construindo uma aplicação completa que extrai, transforma e apresenta dados de uma estrutura JSON complexa.
Essas habilidades são essenciais para trabalhar com dados de APIs, arquivos de configuração e outros cenários de troca de dados. Agora você tem a base para lidar com confiança com dados JSON de qualquer complexidade em suas aplicações Python.
Para aprendizado adicional, considere explorar:
- Trabalhar com APIs reais que retornam dados JSON
- Usar bibliotecas como
pandaspara analisar dados JSON - Implementar validação JSON com
jsonschema - Criar e manipular estruturas JSON personalizadas



