Create a Data Helper in Python for gRPC-style APIs
This code builds a simple DataHelper class that mimics gRPC request/response handling with in-memory storage, JSON serialization, and basic CRUD operations for beginners.
Python code
54 linesimport json
from dataclasses import dataclass, asdict
from typing import Dict, Any
@dataclass
class User:
user_id: int
name: str
email: str
class DataHelper:
"""Simple helper to demonstrate gRPC-like data handling for beginners."""
def __init__(self) -> None:
self._users: Dict[int, User] = {}
def create_user(self, user: User) -> User:
"""Simulates a gRPC CreateUser request."""
self._users[user.user_id] = user
return user
def get_user(self, user_id: int) -> User | None:
"""Simulates a gRPC GetUser request."""
return self._users.get(user_id)
def list_users(self) -> list[User]:
"""Simulates a gRPC ListUsers request."""
return list(self._users.values())
def to_json(self, user: User) -> str:
"""Serialize user to JSON (like protobuf-marshaling)."""
return json.dumps(asdict(user), indent=2)
if __name__ == "__main__":
helper = DataHelper()
# Simulate client requests
alice = helper.create_user(User(user_id=1, name="Alice", email="alice@example.com"))
bob = helper.create_user(User(user_id=2, name="Bob", email="bob@example.com"))
print("Created:", helper.to_json(alice))
print("Fetched:", helper.to_json(helper.get_user(1)))
print("All users:")
for user in helper.list_users():
print(" ", user)
# Show request/response flow
print("\n-- gRPC-like round trip --")
response = helper.get_user(2)
print("Request: GetUser(user_id=2)")
print("Response:", helper.to_json(response) if response else "NOT FOUND")
Output
Created: {
"user_id": 1,
"name": "Alice",
"email": "alice@example.com"
}
Fetched: {
"user_id": 1,
"name": "Alice",
"email": "alice@example.com"
}
All users:
User(user_id=1, name='Alice', email='alice@example.com')
User(user_id=2, name='Bob', email='bob@example.com')
-- gRPC-like round trip --
Request: GetUser(user_id=2)
Response: {
"user_id": 2,
"name": "Bob",
"email": "bob@example.com"
}
How it works
The @dataclass decorator automatically generates __init__, __repr__, and comparison methods, keeping the User model clean. asdict() converts a dataclass instance into a plain dictionary, which json.dumps() then serializes to a JSON string with formatting. The DataHelper uses a dict keyed by user_id for O(1) lookup, mirroring how a gRPC server stores state. The | syntax in User | None and list[User] are Python 3.10+ type hints that make the code self-documenting.
Common mistakes
- Forgetting to call `asdict()` before `json.dumps()` will raise a TypeError because dataclasses aren't JSON serializable by default.
- Assuming `get_user` always returns a User — it can return `None`, so always check before using the result.
- Using mutable default arguments (e.g., `def __init__(self, users={})`) which persist across instances and cause subtle bugs.
Variations
- Use `dataclasses-json` package for automatic serialization/deserialization with JSON.
- Replace the in-memory dict with a real database like SQLite for persistent storage.
Real-world use cases
- Building a mock gRPC server for testing client code without network calls.
- Prototyping an API layer that later converts to actual gRPC service definitions.
- Teaching beginners how to manage request/response data structures in API design.
Sponsored
More from API design & gRPC
- Build a Bulk Array POST Mock Server in Python medium
- Build a Mock REST API with PUT and GET in Python medium
- Convert Protobuf to JSON and Dict in Python easy
- Format data in Python using dataclasses like gRPC messages easy
- Generate an OpenAPI Spec from Mock Routes in Python easy
- How to Add HATEOAS Links to a Python API Response easy
Keep learning
Related tutorials and quizzes for this topic.