Skip to content

Add register_encoder hook for custom API value serialization (#136)#138

Merged
vsdudakov merged 1 commit into
mainfrom
feat/custom-encoders
Jul 5, 2026
Merged

Add register_encoder hook for custom API value serialization (#136)#138
vsdudakov merged 1 commit into
mainfrom
feat/custom-encoders

Conversation

@vsdudakov

Copy link
Copy Markdown
Owner

Closes #136. Also delivers the configurable-format enhancement noted in #135.

What

Adds a small user-facing registry so you can control how a given type is serialized in every admin API response — a custom datetime format, an Enum's label, a domain value object, etc.

import datetime
from fastadmin import register_encoder

# Render every datetime as "2024-01-31 14:05" instead of ISO 8601.
register_encoder(datetime.datetime, lambda dt: dt.strftime("%Y-%m-%d %H:%M"))

Why

Distilled from the fork analysis of this repo. The alex-averin fork added a CUSTOM_ENCODERS dict wired into FastAPI responses (commit, "Add custom encoders for fastapi"). This PR generalizes that idea into a framework-agnostic hook.

Approach

Rather than patch each of the three framework JSON encoders (FastAPI / Flask / Django), custom encoders are applied at the single framework-agnostic serialization point — BaseModelAdmin.serialize_obj_attributes — so all frameworks and ORMs benefit uniformly, and the values reaching each framework's response layer are already JSON-safe.

  • fastadmin/api/encoders.pyregister_encoder / unregister_encoder / clear_encoders / apply_custom_encoders over a CUSTOM_ENCODERS registry.
  • fastadmin/models/base.py — apply custom encoders before the built-in Decimal formatting; a matching encoder takes precedence.
  • fastadmin/__init__.py — export register_encoder / unregister_encoder from the package root.
  • Matching is isinstance in registration order (register more specific types before base types).

Relationship to #135

The concrete "datetime read error" that three forks patched is already fixed in the current codebase (all three frameworks serialize datetime/date/time to ISO 8601, and base.py deserializes the date/time pickers). The one remaining ask in #135configurable output format — is delivered here: register_encoder(datetime.datetime, ...).

Tests

  • tests/api/test_encoders.py — registry unit tests (match order, override, unregister, clear).
  • tests/models/test_base.py — integration: encoder applied during serialization + overrides the built-in Decimal formatting.
  • Full suite: 1975 passed. ruff check, ruff format --check, and ty check all clean.

🤖 Generated with Claude Code

Model field values are serialized to JSON-safe representations in
BaseModelAdmin.serialize_obj_attributes. Add a small user-facing registry
(fastadmin/api/encoders.py) so users can control how a given type is rendered
in every admin API response — e.g. a custom datetime format, an Enum's label,
or a domain value object.

Custom encoders are matched via isinstance in registration order and take
precedence over the built-in datetime/UUID/Decimal handling, which also
provides the configurable datetime output requested in #135.

- fastadmin/api/encoders.py: register_encoder / unregister_encoder /
  clear_encoders / apply_custom_encoders + CUSTOM_ENCODERS registry
- base.py: apply custom encoders before the built-in Decimal formatting
- expose register_encoder / unregister_encoder from the package root
- docs + changelog + unit/integration tests

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vsdudakov vsdudakov merged commit 8196186 into main Jul 5, 2026
12 checks passed
@vsdudakov vsdudakov deleted the feat/custom-encoders branch July 5, 2026 12:56
@vsdudakov vsdudakov mentioned this pull request Jul 5, 2026
vsdudakov added a commit that referenced this pull request Jul 5, 2026
Bump version 0.7.0 -> 0.8.0 and finalize the changelog for the
register_encoder custom-serialization hook (#136, #138).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom serialization / encoders hook for response values

1 participant