cattrs

Structuring and unstructuring library for attrs/dataclasses — converts between Python objects and primitive data (dicts, lists) for serialization. cattrs features: structure() for dict→object conversion, unstructure() for object→dict conversion, Converter for custom serialization rules, GenConverter with generics support, register_structure_hook/register_unstructure_hook for custom types, ClassValidationError with per-field errors, cattrs.preconf.json for JSON-ready converters, support for attrs, dataclasses, TypedDict, NamedTuple, and most typing constructs (Union, Optional, List, Dict), and exception groups for multiple field errors.

Evaluated Mar 06, 2026 (0d ago) v23.x
Homepage ↗ Repo ↗ Developer Tools python cattrs attrs serialization deserialization structuring unstructuring
⚙ Agent Friendliness
69
/ 100
Can an agent use this?
🔒 Security
92
/ 100
Is it safe for agents?
⚡ Reliability
86
/ 100
Does it work consistently?

Score Breakdown

⚙ Agent Friendliness

MCP Quality
--
Documentation
88
Error Messages
85
Auth Simplicity
99
Rate Limits
99

🔒 Security

TLS Enforcement
92
Auth Strength
92
Scope Granularity
92
Dep. Hygiene
92
Secret Handling
90

Pure serialization library. structure() deserializes untrusted data — validators in attrs classes run during structure(); ensure all attrs validators are properly defined. Unstructuring to dict does not sanitize data — validate before structuring from user input.

⚡ Reliability

Uptime/SLA
88
Version Stability
85
Breaking Changes
82
Error Recovery
88
AF Security Reliability

Best When

attrs/dataclass serialization with custom types, complex nesting, and Union types — cattrs is the standard serialization companion for attrs classes.

Avoid When

API schema generation (use Pydantic), simple attrs serialization (use attrs.asdict()), or when Pydantic's integrated validation is needed.

Use Cases

  • Agent attrs to dict — import cattrs; import attrs; @attrs.define; class User: id: int; name: str; email: str; user = User(1, 'Alice', 'a@b.com'); d = cattrs.unstructure(user) — {'id': 1, 'name': 'Alice', 'email': 'a@b.com'}; user2 = cattrs.structure(d, User) — round-trip; agent converts attrs objects to dicts for JSON serialization
  • Agent nested structuring — @attrs.define; class Order: id: int; user: User; items: list[str]; data = {'id': 99, 'user': {'id': 1, 'name': 'Alice', 'email': 'a@b.com'}, 'items': ['book', 'pen']}; order = cattrs.structure(data, Order) — nested; agent structures nested dicts recursively; all nested attrs/dataclass fields are structured automatically
  • Agent custom converter — from cattrs import Converter; c = Converter(); c.register_unstructure_hook(datetime, lambda dt: dt.isoformat()); c.register_structure_hook(datetime, lambda v, _: datetime.fromisoformat(v)); d = c.unstructure(user_with_datetime) — custom types; agent registers converters for types cattrs doesn't handle by default (datetime, UUID, Decimal)
  • Agent JSON preset — from cattrs.preconf.json import make_json_converter; c = make_json_converter(); json_dict = c.unstructure(obj) — JSON-ready; agent uses pre-configured converter that handles datetime→ISO string, bytes→base64, UUID→string; unstructure produces JSON-serializable dict directly; then json.dumps(json_dict)
  • Agent validation errors — from cattrs import ClassValidationError; try: obj = cattrs.structure(data, MyClass) except ClassValidationError as e: for exc in e.exceptions: print(exc.exc_type, exc.path) — validation; agent catches structured exceptions with per-field error details; ClassValidationError has .exceptions list with path to each failed field

Not For

  • API serialization with schema generation — cattrs has no OpenAPI/JSON Schema output; for API use Pydantic which generates schemas
  • Validation with rich error messages — Pydantic v2 has better validation error messages for user-facing APIs
  • Simple dict serialization — for attrs without complex nesting, attrs.asdict() is sufficient; cattrs shines for complex types

Interface

REST API
No
GraphQL
No
gRPC
No
MCP Server
No
SDK
Yes
Webhooks
No

Authentication

Methods: none
OAuth: No Scopes: No

No auth — serialization library.

Pricing

Model: open_source
Free tier: Yes
Requires CC: No

cattrs is MIT licensed. Part of the attrs ecosystem. Free for all use.

Agent Metadata

Pagination
none
Idempotent
Full
Retry Guidance
Not documented

Known Gotchas

  • Default converter is global and shared — cattrs.structure() uses a global default Converter; registering hooks on default converter affects all code using it; agent code: create a custom Converter() for app-specific hooks instead of modifying global; from cattrs import Converter; c = Converter() — isolated converter
  • Union types need disambiguation — cattrs.structure({'x': 1}, Union[ClassA, ClassB]) may fail without discriminator; cattrs tries each type in order; agent code with Union: add discriminator field or use register_structure_hook to implement custom Union logic; or use Literal-tagged unions with GenConverter
  • datetime not handled by default converter — cattrs.structure('2024-01-15T14:30:00', datetime) raises StructureError by default; agent code: use make_json_converter() from cattrs.preconf.json which handles datetime, UUID, bytes; or register_structure_hook(datetime, ...) on custom converter
  • unstructure returns plain dicts not JSON — cattrs.unstructure(obj) returns Python dict; may contain non-JSON-serializable types (datetime, UUID); json.dumps(cattrs.unstructure(obj)) may raise TypeError; agent code: use make_json_converter() which handles common non-JSON types; or register unstructure hooks for each special type
  • ClassValidationError requires explicit handling — cattrs.structure() with invalid data raises ClassValidationError (not ValueError/TypeError); agent code: catch ClassValidationError specifically to get field-level errors; generic except Exception misses the structured error info; import ClassValidationError from cattrs
  • Slots attrs classes need GenConverter — @attrs.define (slots=True by default) works with default Converter; but complex generic types (List[MyClass], Optional[MyClass]) work better with GenConverter: from cattrs import GenConverter; c = GenConverter() — generates optimized code for generic types; default Converter works for most cases

Alternatives

Full Evaluation Report

Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for cattrs.

$99

Scores are editorial opinions as of 2026-03-06.

5208
Packages Evaluated
26151
Need Evaluation
173
Need Re-evaluation
Community Powered