{"id":13550255,"url":"https://github.com/dtolnay/erased-serde","last_synced_at":"2025-05-13T21:04:42.209Z","repository":{"id":37484599,"uuid":"66216301","full_name":"dtolnay/erased-serde","owner":"dtolnay","description":"Type-erased Serialize, Serializer and Deserializer traits","archived":false,"fork":false,"pushed_at":"2025-03-03T23:29:20.000Z","size":588,"stargazers_count":768,"open_issues_count":9,"forks_count":37,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-28T12:08:25.441Z","etag":null,"topics":["rust","serde"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dtolnay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"dtolnay"}},"created_at":"2016-08-21T19:18:01.000Z","updated_at":"2025-04-28T01:03:32.000Z","dependencies_parsed_at":"2023-02-17T13:16:08.742Z","dependency_job_id":"33bafdef-c31d-41a8-b7c0-fa69dce78527","html_url":"https://github.com/dtolnay/erased-serde","commit_stats":{"total_commits":310,"total_committers":6,"mean_commits":"51.666666666666664","dds":"0.029032258064516148","last_synced_commit":"1ea7a7aecd4a344cabd58d0c6c308dc43624522d"},"previous_names":[],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtolnay%2Ferased-serde","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtolnay%2Ferased-serde/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtolnay%2Ferased-serde/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtolnay%2Ferased-serde/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dtolnay","download_url":"https://codeload.github.com/dtolnay/erased-serde/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251311330,"owners_count":21569009,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rust","serde"],"created_at":"2024-08-01T12:01:30.759Z","updated_at":"2025-04-28T12:08:31.286Z","avatar_url":"https://github.com/dtolnay.png","language":"Rust","funding_links":["https://github.com/sponsors/dtolnay"],"categories":["Rust"],"sub_categories":[],"readme":"Erased Serde\n============\n\n[\u003cimg alt=\"github\" src=\"https://img.shields.io/badge/github-dtolnay/erased--serde-8da0cb?style=for-the-badge\u0026labelColor=555555\u0026logo=github\" height=\"20\"\u003e](https://github.com/dtolnay/erased-serde)\n[\u003cimg alt=\"crates.io\" src=\"https://img.shields.io/crates/v/erased-serde.svg?style=for-the-badge\u0026color=fc8d62\u0026logo=rust\" height=\"20\"\u003e](https://crates.io/crates/erased-serde)\n[\u003cimg alt=\"docs.rs\" src=\"https://img.shields.io/badge/docs.rs-erased--serde-66c2a5?style=for-the-badge\u0026labelColor=555555\u0026logo=docs.rs\" height=\"20\"\u003e](https://docs.rs/erased-serde)\n[\u003cimg alt=\"build status\" src=\"https://img.shields.io/github/actions/workflow/status/dtolnay/erased-serde/ci.yml?branch=master\u0026style=for-the-badge\" height=\"20\"\u003e](https://github.com/dtolnay/erased-serde/actions?query=branch%3Amaster)\n\nThis crate provides type-erased versions of Serde's `Serialize`, `Serializer`\nand `Deserializer` traits that can be used as [trait objects].\n\n[trait objects]: https://doc.rust-lang.org/book/first-edition/trait-objects.html\n\n- [`erased_serde::Serialize`](https://docs.rs/erased-serde/0.4/erased_serde/trait.Serialize.html)\n- [`erased_serde::Serializer`](https://docs.rs/erased-serde/0.4/erased_serde/trait.Serializer.html)\n- [`erased_serde::Deserializer`](https://docs.rs/erased-serde/0.4/erased_serde/trait.Deserializer.html)\n\nThe usual Serde `Serialize`, `Serializer` and `Deserializer` traits cannot be\nused as trait objects like `\u0026dyn Serialize` or boxed trait objects like\n`Box\u003cdyn Serialize\u003e` because of Rust's [\"object safety\" rules]. In particular,\nall three traits contain generic methods which cannot be made into a trait\nobject.\n\n[\"object safety\" rules]: http://huonw.github.io/blog/2015/01/object-safety/\n\nThis library should be considered a low-level building block for interacting\nwith Serde APIs in an object-safe way. Most use cases will require higher level\nfunctionality such as provided by [`typetag`] which uses this crate internally.\n\n[`typetag`]: https://github.com/dtolnay/typetag\n\n**The traits in this crate work seamlessly with any existing Serde `Serialize`\nand `Deserialize` type and any existing Serde `Serializer` and `Deserializer`\nformat.**\n\n```toml\n[dependencies]\nserde = \"1.0\"\nerased-serde = \"0.4\"\n```\n\n## Serialization\n\n```rust\nuse erased_serde::{Serialize, Serializer};\nuse std::collections::BTreeMap as Map;\nuse std::io;\n\nfn main() {\n    // Construct some serializers.\n    let json = \u0026mut serde_json::Serializer::new(io::stdout());\n    let cbor = \u0026mut serde_cbor::Serializer::new(serde_cbor::ser::IoWrite::new(io::stdout()));\n\n    // The values in this map are boxed trait objects. Ordinarily this would not\n    // be possible with serde::Serializer because of object safety, but type\n    // erasure makes it possible with erased_serde::Serializer.\n    let mut formats: Map\u003c\u0026str, Box\u003cdyn Serializer\u003e\u003e = Map::new();\n    formats.insert(\"json\", Box::new(\u003cdyn Serializer\u003e::erase(json)));\n    formats.insert(\"cbor\", Box::new(\u003cdyn Serializer\u003e::erase(cbor)));\n\n    // These are boxed trait objects as well. Same thing here - type erasure\n    // makes this possible.\n    let mut values: Map\u003c\u0026str, Box\u003cdyn Serialize\u003e\u003e = Map::new();\n    values.insert(\"vec\", Box::new(vec![\"a\", \"b\"]));\n    values.insert(\"int\", Box::new(65536));\n\n    // Pick a Serializer out of the formats map.\n    let format = formats.get_mut(\"json\").unwrap();\n\n    // Pick a Serialize out of the values map.\n    let value = values.get(\"vec\").unwrap();\n\n    // This line prints `[\"a\",\"b\"]` to stdout.\n    value.erased_serialize(format).unwrap();\n}\n```\n\n## Deserialization\n\n```rust\nuse erased_serde::Deserializer;\nuse std::collections::BTreeMap as Map;\n\nfn main() {\n    static JSON: \u0026[u8] = br#\"{\"A\": 65, \"B\": 66}\"#;\n    static CBOR: \u0026[u8] = \u0026[162, 97, 65, 24, 65, 97, 66, 24, 66];\n\n    // Construct some deserializers.\n    let json = \u0026mut serde_json::Deserializer::from_slice(JSON);\n    let cbor = \u0026mut serde_cbor::Deserializer::from_slice(CBOR);\n\n    // The values in this map are boxed trait objects, which is not possible\n    // with the normal serde::Deserializer because of object safety.\n    let mut formats: Map\u003c\u0026str, Box\u003cdyn Deserializer\u003e\u003e = Map::new();\n    formats.insert(\"json\", Box::new(\u003cdyn Deserializer\u003e::erase(json)));\n    formats.insert(\"cbor\", Box::new(\u003cdyn Deserializer\u003e::erase(cbor)));\n\n    // Pick a Deserializer out of the formats map.\n    let format = formats.get_mut(\"json\").unwrap();\n\n    let data: Map\u003cString, usize\u003e = erased_serde::deserialize(format).unwrap();\n\n    println!(\"{}\", data[\"A\"] + data[\"B\"]);\n}\n```\n\n## How it works\n\nThis crate is based on a general technique for building trait objects of traits\nthat have generic methods (like all of Serde's traits). [This example code]\ndemonstrates the technique applied to a simplified case of a single generic\nmethod. [Try it in the playground.]\n\n[This example code]: https://github.com/dtolnay/erased-serde/blob/master/explanation/main.rs\n[Try it in the playground.]: https://play.rust-lang.org/?gist=c1111875e7462ba3d0190aacb2fc2211\n\nIn erased-serde things are a bit more complicated than in the example for three\nreasons but the idea is the same.\n\n- We need to deal with trait methods that take `self` by value -- effectively by\n  implementing the object-safe trait for `Option\u003cT\u003e` where `T` implements the\n  real trait.\n- We need to deal with traits that have associated types like `Serializer::Ok`\n  and `Visitor::Value` -- by carefully short-term stashing things behind a\n  pointer.\n- We need to support trait methods that have a generic type in the return type\n  but none of the argument types, like `SeqAccess::next_element` -- this can be\n  flipped around into a callback style where the return value is instead passed\n  on to a generic argument.\n\nIn the future maybe the Rust compiler will be able to apply this technique\nautomatically to any trait that is not already object safe by the current rules.\n\n\u003cbr\u003e\n\n#### License\n\n\u003csup\u003e\nLicensed under either of \u003ca href=\"LICENSE-APACHE\"\u003eApache License, Version\n2.0\u003c/a\u003e or \u003ca href=\"LICENSE-MIT\"\u003eMIT license\u003c/a\u003e at your option.\n\u003c/sup\u003e\n\n\u003cbr\u003e\n\n\u003csub\u003e\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in this crate by you, as defined in the Apache-2.0 license, shall\nbe dual licensed as above, without any additional terms or conditions.\n\u003c/sub\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtolnay%2Ferased-serde","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdtolnay%2Ferased-serde","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtolnay%2Ferased-serde/lists"}