erased-serde

Type-erased Serialize and Serializer/Deserializer traits for Serde, usable as trait objects

Library
Cargo
v0.4.10
822stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
60/100Good
Development Activity60
Maintenance48
Community44
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture80
Code Quality82
Innovation75
Learning Curve55

erased-serde provides type-erased versions of Serde’s Serialize, Serializer, and Deserializer traits so they can be used as trait objects (&dyn Serialize, Box<dyn Serialize>). Serde’s own traits contain generic methods and therefore aren’t object-safe under Rust’s rules, which normally makes dynamic dispatch over heterogeneous serializable types impossible.

Written by prolific Rust ecosystem maintainer David Tolnay, this crate is a low-level building block — most application code will reach for a higher-level crate like typetag (which uses erased-serde internally) rather than using it directly, but it is the foundational piece that makes trait-object-based serialization work at all with any existing Serde-compatible type and format.

What You Get

  • erased_serde::Serialize — an object-safe drop-in trait object substitute for serde::Serialize
  • erased_serde::Serializer and erased_serde::Deserializer — object-safe wrappers for Serde’s serializer/deserializer traits
  • Seamless interop with any existing Serde Serialize/Deserialize type and any existing Serde data format (JSON, CBOR, etc.) with no changes needed on either side
  • no_std support via alloc/std feature flags for constrained environments
  • A build.rs-based feature-detection setup and criterion-based benchmarks validating the erasure has minimal overhead

Common Use Cases

  • Storing heterogeneous serializable values in a single collection, e.g. Vec<Box<dyn erased_serde::Serialize>>
  • Building plugin systems where serializable trait objects need to cross a dynamic-dispatch boundary
  • Implementing polymorphic (de)serialization for enum-like or trait-based value hierarchies, often via the higher-level typetag crate
  • Writing library code that needs to accept ‘any Serde-serializable type’ as a trait object parameter rather than a generic

Under The Hood

Architecture: The crate’s ~4,000 lines of src/ are organized around a small set of focused modules — ser.rs and de.rs implement the erased Serializer/Deserializer traits by manually forwarding each of Serde’s generic trait methods through a non-generic vtable-like dispatch, any.rs provides the Any-style type-erasure primitives underpinning this, error.rs normalizes error types across formats, and sealed.rs/private.rs lock down the trait implementations to prevent external types from implementing the erased traits incorrectly (a common pattern in dtolnay’s crates to preserve soundness invariants). map.rs handles map-serialization erasure specifically since Serde’s map serialization API is one of the trickiest to make object-safe. Tech Stack: Minimal dependencies — serde_core (the trait-only subset of serde) and typeid for the crate’s runtime type-erasure primitives — with serde itself only pulled in via a cfg(any()) dependency trick to satisfy documentation tooling without an actual build dependency, keeping the erasure layer as thin as possible. The crate supports Rust edition 2021 with an MSRV of 1.68 and works in no_std contexts via feature flags. Code Quality: Testing centers on tests/readme.rs, which validates the README’s own code examples compile and run correctly (a common dtolnay-crate pattern ensuring documentation never drifts from working code), supplemented by trybuild for compile-fail testing of the sealed-trait boundaries and criterion benchmarks confirming erasure overhead stays negligible. API Design: The traits are designed as a near drop-in replacement — code written against serde::Serialize typically needs only the import changed to erased_serde::Serialize to gain trait-object support, and the crate explicitly documents interop with any existing Serde type/format with zero required changes on either side, which is the core design goal and its main ergonomic win.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search