diff --git a/tech_docs/python/json_python.md b/tech_docs/python/json_python.md index 868ea32..05fab35 100644 --- a/tech_docs/python/json_python.md +++ b/tech_docs/python/json_python.md @@ -1,3 +1,208 @@ +# Comprehensive Guide to Working with JSON in Python + +## Introduction + +JSON (JavaScript Object Notation) is a lightweight data interchange format that's easy for humans to read and write and easy for machines to parse and generate. Python's built-in `json` library provides tools to work with JSON data, allowing you to serialize and deserialize Python objects. + +## Basic Operations + +### Encoding (Serialization) + +Serialization is the process of converting a Python object into a JSON string. This is useful for saving data to a file or sending it over a network. + +#### Convert Python Object to JSON String + +```python +import json + +data = { + "name": "John Doe", + "age": 30, + "isEmployed": True, + "skills": ["Python", "Machine Learning", "Web Development"] +} + +json_string = json.dumps(data, indent=4) +print(json_string) +``` + +#### Write JSON Data to a File + +```python +with open('data.json', 'w') as file: + json.dump(data, file, indent=4) +``` + +### Decoding (Deserialization) + +Deserialization is the process of converting a JSON string back into a Python object. This is useful for loading data from a file or receiving it from a network. + +#### Convert JSON String to Python Object + +```python +json_string = '{"name": "Jane Doe", "age": 25, "isEmployed": false}' +python_object = json.loads(json_string) +print(python_object) +``` + +#### Read JSON Data from a File + +```python +with open('data.json', 'r') as file: + python_object = json.load(file) + print(python_object) +``` + +## Advanced Usage + +### Custom Object Encoding and Decoding + +The `json` library can be extended to encode custom objects and decode JSON into specific Python classes. + +#### Encoding Custom Objects + +```python +class User: + def __init__(self, name, age): + self.name = name + self.age = age + +def encode_user(obj): + if isinstance(obj, User): + return {"name": obj.name, "age": obj.age, "__User__": True} + return obj + +user = User("John Doe", 30) +json_string = json.dumps(user, default=encode_user) +print(json_string) +``` + +#### Decoding JSON into Custom Python Objects + +```python +def decode_user(dct): + if "__User__" in dct: + return User(dct["name"], dct["age"]) + return dct + +user = json.loads(json_string, object_hook=decode_user) +print(user.name, user.age) +``` + +## JSON Querying in Python + +When working with JSON in Python, you might need to navigate and manipulate nested structures of dictionaries and lists. Here are some common operations: + +### Accessing Nested Elements + +```python +json_data = ''' +{ + "person": { + "name": "John Doe", + "address": { + "street": "123 Main St", + "city": "Anytown", + "zipcode": "12345" + }, + "phone_numbers": [ + {"type": "home", "number": "555-1234"}, + {"type": "work", "number": "555-5678"} + ] + } +} +''' + +data = json.loads(json_data) + +# Accessing nested elements +print(data['person']['name']) # Output: John Doe +print(data['person']['address']['city']) # Output: Anytown +print(data['person']['phone_numbers'][0]['number']) # Output: 555-1234 +``` + +### Iterating Over Lists + +```python +# Iterating over phone numbers +for phone in data['person']['phone_numbers']: + print(f"{phone['type'].capitalize()} phone: {phone['number']}") +``` + +### Filtering Data + +```python +# Filter products that cost more than $2 +expensive_products = [product for product in data['products'] if product['price'] > 2] +print("Expensive products:", [product['name'] for product in expensive_products]) +``` + +### Transforming Data + +```python +# Add a 'discounted_price' field to each product (10% discount) +discounted_products = [ + {**product, 'discounted_price': product['price'] * 0.9} + for product in data['products'] +] + +print(json.dumps(discounted_products, indent=2)) +``` + +### Aggregating Data + +```python +# Calculate the total value of all products +total_value = sum(product['price'] for product in data['products']) +print(f"Total value of all products: ${total_value:.2f}") +``` + +### Searching for Specific Items + +```python +# Find the first product that costs exactly $3.00 +product_3_dollars = next((product for product in data['products'] if product['price'] == 3.0), None) +print("First $3 product:", product_3_dollars['name'] if product_3_dollars else "Not found") +``` + +### Handling Missing Keys + +```python +for product in data['products']: + # Using get() with a default value + print(f"Product: {product.get('name', 'Unnamed')}, " + f"Price: ${product.get('price', 0):.2f}, " + f"Stock: {product.get('stock', 'Unknown')}") +``` + +## Use Cases + +- **Configuration Files**: JSON is often used to store configuration settings for applications. Its human-readable format makes it easy to update and manage settings. +- **Data Interchange**: JSON is a common format for data exchange between servers and web applications, especially in RESTful APIs. +- **Storing and Retrieving Data**: JSON can be used to store data persistently in files, which can be later retrieved and processed. + +## Best Practices + +- **Handling Exceptions**: Always handle exceptions when parsing JSON to manage malformed data gracefully. + + ```python + try: + data = json.loads(malformed_json_string) + except json.JSONDecodeError as e: + print(f"Error decoding JSON: {e}") + ``` + +- **Security Considerations**: Be cautious when deserializing JSON from untrusted sources to avoid security vulnerabilities. + +- **Pretty Printing**: Use the `indent` parameter in `json.dumps()` or `json.dump()` for pretty printing, making JSON data easier to read and debug. + + ```python + json_string = json.dumps(data, indent=4) + print(json_string) + ``` + +--- + Certainly! Understanding `json` module functions like `load`, `loads`, `dump`, and `dumps` is crucial for effective serialization and deserialization in Python. Here’s a breakdown of these functions and some helpful reminders: ### JSON Functions in Python