Skip to main content

expli

Explicit dataclasses with automatic serialization

expli (short for "explicit") enhances Python dataclasses with automatic dictionary and JSON serialization methods, making it effortless to work with nested dataclasses, optional types, and lists.

Installation

pip install expli

Quick Start

from expli import edataclass

@edataclass
class Person:
    name: str
    age: int
    email: str | None = None

# Automatic methods are added!
person = Person("Alice", 30, "alice@example.com")

# Convert to dict
data = person.to_dict()

# Convert to JSON
json_str = person.to_json(indent=2)

# Create from dict
person2 = Person.from_dict(data)

# Create from JSON
person3 = Person.from_json(json_str)

# Create a copy/clone
person4 = person.copy()
person5 = person.clone()  # Same as copy()

Features

🎯 Enhanced Dataclass Decorator

The @edataclass decorator automatically adds six methods to your dataclass:

  • to_dict() - Convert instance to dictionary
  • from_dict(data) - Create instance from dictionary (class method)
  • to_json(indent=None) - Convert instance to JSON string
  • from_json(json_str) - Create instance from JSON string (class method)
  • copy() - Create a copy of the instance
  • clone() - Create a clone of the instance (alias for copy())

🔄 Full Recursive Support

expli handles complex nested structures automatically:

from expli import edataclass

@edataclass
class Address:
    street: str
    city: str
    country: str

@edataclass
class Company:
    name: str
    address: Address

@edataclass
class Person:
    name: str
    age: int
    company: Company | None
    hobbies: list[str]

person = Person(
    name="Alice",
    age=30,
    company=Company(
        name="Tech Corp",
        address=Address("123 Main St", "Boston", "USA")
    ),
    hobbies=["reading", "coding"]
)

# Everything serializes recursively
data = person.to_dict()
# {
#     "name": "Alice",
#     "age": 30,
#     "company": {
#         "name": "Tech Corp",
#         "address": {
#             "street": "123 Main St",
#             "city": "Boston",
#             "country": "USA"
#         }
#     },
#     "hobbies": ["reading", "coding"]
# }

# And deserializes back perfectly
person2 = Person.from_dict(data)

# Create a copy with all nested objects copied
person_copy = person.copy()

🔄 Copying and Cloning

Create independent copies of your dataclass instances:

from expli import edataclass

@edataclass
class Person:
    name: str
    age: int
    hobbies: list[str]

person = Person("Alice", 30, ["reading", "coding"])

# Create a copy
person_copy = person.copy()
# or use clone() - they're the same
person_clone = person.clone()

# The copy is independent
person_copy.hobbies.append("gaming")
print(person.hobbies)       # ["reading", "coding"]
print(person_copy.hobbies)  # ["reading", "coding", "gaming"]

✨ Supported Types

  • Primitive types: str, int, float, bool, etc.
  • Optional types: Type | None
  • Lists: list[Type]
  • Nested dataclasses: Any dataclass as a field
  • Lists of dataclasses: list[DataclassType]
  • Optional lists: list[Type] | None

🛠️ Dataclass Parameters

@edataclass supports all standard dataclass parameters:

from expli import edataclass

@edataclass(frozen=True, order=True)
class Config:
    api_key: str
    timeout: int = 30

API Reference

@edataclass

Enhanced dataclass decorator that adds serialization methods.

Parameters: Same as @dataclass (frozen, order, etc.)

Added Methods:

  • to_dict(self) -> dict - Convert instance to dictionary
  • from_dict(cls, data: dict) -> Self - Create instance from dictionary
  • to_json(self, indent=None) -> str - Convert instance to JSON string
  • from_json(cls, json_str: str) -> Self - Create instance from JSON string
  • copy(self) -> Self - Create a copy of the instance
  • clone(self) -> Self - Create a clone of the instance (alias for copy())

to_dict(obj) / easdict(obj)

Standalone function to convert a dataclass instance to a dictionary.

from expli import to_dict, easdict
from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

point = Point(10, 20)
data = to_dict(point)  # or easdict(point)
# {"x": 10, "y": 20}

from_dict(cls, data) / efromdict(cls, data)

Standalone function to create a dataclass instance from a dictionary.

from expli import from_dict, efromdict
from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

data = {"x": 10, "y": 20}
point = from_dict(Point, data)  # or efromdict(Point, data)

Why expli?

Standard dataclasses don't provide built-in serialization for nested structures. While dataclasses.asdict() exists, it doesn't handle deserialization, and neither function is added to your class for convenient access.

expli solves this by:

  • ✅ Adding methods directly to your dataclass
  • ✅ Handling nested dataclasses recursively
  • ✅ Supporting optional types and lists
  • ✅ Providing both dict and JSON serialization
  • ✅ Working seamlessly with type hints
  • ✅ Easy copying and cloning of instances

Comparison

Without expli:

from dataclasses import dataclass, asdict
import json

@dataclass
class Person:
    name: str
    age: int

person = Person("Alice", 30)

# Manual serialization
data = asdict(person)
json_str = json.dumps(data)

# Manual deserialization (you have to write this!)
def from_dict(data):
    return Person(**data)

person2 = from_dict(json.loads(json_str))

With expli:

from expli import edataclass

@edataclass
class Person:
    name: str
    age: int

person = Person("Alice", 30)

# Built-in methods
data = person.to_dict()
json_str = person.to_json()
person2 = Person.from_dict(data)
person3 = Person.from_json(json_str)
person4 = person.copy()

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Metadata

Release files for expli 0.0.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for expli 0.0.4
File Size Uploaded
expli-0.0.4.tar.gz 6.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for expli 0.0.4
File Interpreter ABI Platform
expli-0.0.4-py3-none-any.whl Python 3 none any Details

Total release size: 12.6 kB

Release files / expli-0.0.4.tar.gz

Download URL expli-0.0.4.tar.gz
Size 6.1 kB
Tags Source
SHA-256 checksum
How to use checksums
118f78e3860c8a9c06acb07ce8ad22b944e0f796f680f22820787ccfbdf9f124
BLAKE2b-256 checksum
How to use checksums
b3b0dc0a18872a2248e95588654bf72b6c69a5a579438174d5ec19d72c43c6d7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.5

Release files / expli-0.0.4-py3-none-any.whl

Download URL expli-0.0.4-py3-none-any.whl
Size 6.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1419c169b29c5bc6c9b761658c29397ad52c430588d8c5d6eaa3f128e963d0f0
BLAKE2b-256 checksum
How to use checksums
626a70ac3188ec84c9ea2f162eb86b82b97f6e32c542cf5cf102aa2c1520fcec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.5
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page