Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dtolnay/serde-untagged
Serde Visitor for deserializing untagged enums
https://github.com/dtolnay/serde-untagged
serde
Last synced: about 8 hours ago
JSON representation
Serde Visitor for deserializing untagged enums
- Host: GitHub
- URL: https://github.com/dtolnay/serde-untagged
- Owner: dtolnay
- License: apache-2.0
- Created: 2023-08-26T01:18:54.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2024-10-06T21:50:06.000Z (3 months ago)
- Last Synced: 2024-10-14T17:13:42.174Z (3 months ago)
- Topics: serde
- Language: Rust
- Homepage:
- Size: 210 KB
- Stars: 60
- Watchers: 2
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE-APACHE
Awesome Lists containing this project
README
serde-untagged
==============[](https://github.com/dtolnay/serde-untagged)
[](https://crates.io/crates/serde-untagged)
[](https://docs.rs/serde-untagged)
[](https://github.com/dtolnay/serde-untagged/actions?query=branch%3Amaster)This crate provides a Serde `Visitor` implementation that is useful for
deserializing untagged enums.```toml
[dependencies]
serde-untagged = "0.1"
```
Untagged enum `Deserialize` impls look like this:
```rust
use serde::de::{Deserialize, Deserializer};
use serde_untagged::UntaggedEnumVisitor;impl<'de> Deserialize<'de> for $MyType {
fn deserialize(deserializer: D) -> Result
where
D: Deserializer<'de>,
{
UntaggedEnumVisitor::new()
/*
*
*/
.deserialize(deserializer)
}
}
```Inside the `/* ... */`, we list each type that the untagged enum needs to
support deserializing from, giving a closure that turns the input into $MyType.
The following types are supported:- bool
- i8, i16, i32, i64, i128, u8, u16, u32, u64, u128
- f32
- f64
- char
- string
- borrowed\_str
- bytes
- borrowed\_bytes
- byte\_buf
- unit
- seq
- map### Example: string or struct
Cargo's `http.ssl-version` configuration supports deserialization from the
following two representations:```toml
[http]
ssl-version = "tlsv1.3"
``````toml
[http]
ssl-version.min = "tlsv1.2"
ssl-version.max = "tlsv1.3"
``````rust
use serde::de::{Deserialize, Deserializer};
use serde_derive::Deserialize;
use serde_untagged::UntaggedEnumVisitor;pub enum SslVersionConfig {
Single(String),
Range(SslVersionConfigRange),
}impl<'de> Deserialize<'de> for SslVersionConfig {
fn deserialize(deserializer: D) -> Result
where
D: Deserializer<'de>,
{
UntaggedEnumVisitor::new()
.string(|single| Ok(SslVersionConfig::Single(single.to_owned())))
.map(|map| map.deserialize().map(SslVersionConfig::Range))
.deserialize(deserializer)
}
}#[derive(Deserialize)]
pub struct SslVersionConfigRange {
pub min: Option,
pub max: Option,
}
```### Example: unit variant or bool
Cargo's LTO setting in profiles supports the 5 values `false`, `true`, `"fat"`,
`"thin"`, and `"off"`.```toml
[profile.release]
lto = "thin"
``````rust
use serde::de::{Deserialize, Deserializer, IntoDeserializer};
use serde_derive::Deserialize;
use serde_untagged::UntaggedEnumVisitor;pub enum LinkTimeOptimization {
Enabled(bool),
Enum(LinkTimeOptimizationString),
}impl<'de> Deserialize<'de> for LinkTimeOptimization {
fn deserialize(deserializer: D) -> Result
where
D: Deserializer<'de>,
{
UntaggedEnumVisitor::new()
.bool(|b| Ok(LinkTimeOptimization::Enabled(b)))
.string(|string| {
let de = string.into_deserializer();
LinkTimeOptimizationString::deserialize(de).map(LinkTimeOptimization::Enum)
})
.deserialize(deserializer)
}
}#[derive(Deserialize)]
#[serde(rename = "lowercase")]
pub enum LinkTimeOptimizationString {
Fat,
Thin,
Off,
}
```Since `lto = true` means the same thing as `lto = "fat"` to Cargo, there are
really only 4 distinct options. This type could be implemented alternatively as:```rust
use serde::de::{Deserialize, Deserializer, Unexpected};
use serde_untagged::UntaggedEnumVisitor;pub enum LinkTimeOptimization {
ThinLocal, // false
Fat, // true or "fat"
Thin, // "thin"
Off, // "off"
}impl<'de> Deserialize<'de> for LinkTimeOptimization {
fn deserialize(deserializer: D) -> Result
where
D: Deserializer<'de>,
{
UntaggedEnumVisitor::new()
.bool(|b| match b {
false => Ok(LinkTimeOptimization::ThinLocal),
true => Ok(LinkTimeOptimization::Fat),
})
.string(|string| match string {
"fat" => Ok(LinkTimeOptimization::Fat),
"thin" => Ok(LinkTimeOptimization::Thin),
"off" => Ok(LinkTimeOptimization::Off),
_ => Err(serde::de::Error::invalid_value(
Unexpected::Str(string),
&r#""fat" or "thin" or "off""#,
)),
})
.deserialize(deserializer)
}
}
```
#### License
Licensed under either of Apache License, Version
2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.