NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #330 most downloaded on crates.io
Custom de/serialization functions for Rust's serde
Last release 12 days ago
26 Sep 2026
Release timing varies
gaps range from 2 weeks to 3 months
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
9 years old
78 releases · first in 2017
Implement JsonSchemaAs for NoneAsEmptyString , so fields using it compile with the schemars_* features
JsonSchemaAs for NoneAsEmptyString, so fields using it compile with the schemars_* features (#1014)with_prefix! and with_suffix! available with the alloc feature, instead of only with std (#1008)Update syn and darling dependencies to use syn v3
syn and darling dependencies to use syn v3 (#992)base64 to a newer version. This should not have any API change, but some error messages might change. (#993)serde_as can now parse cfg_attr(true, ...) and cfg_attr(false, ...) (#995)true/false are new literals as of Rust 1.88 but need to be parsed explicitly with the syn types.schemars annotations.One column per quarter.
Add support for jiff v0.2 behind the new jiff_0_2 feature flag ( #936 ) jiff::SignedDuration works with DurationSeconds and its variants. jiff::Timest
jiff v0.2 behind the new jiff_0_2 feature flag (#936)jiff::SignedDuration works with DurationSeconds and its variants.jiff::Timestamp, jiff::Zoned, and jiff::civil::DateTime work with TimestampSeconds and its variants.jiff::Zoned uses the system time zone, like chrono::DateTime<Local>.rust::sets_duplicate_value_is_error, rust::maps_duplicate_key_is_error, rust::sets_last_value_wins, and rust::maps_first_key_wins adapters created their backing sets/maps with with_capacity_and_hasher using the raw deserializer size_hint, bypassing the size_hint_cautious cap added in #966 (the clippy.toml disallowed_methods lint only covers Vec::with_capacity, not with_capacity_and_hasher, so these sites were not flagged).Hash table capacity overflow before a single element was read. All such constructions now route through size_hint_cautious.GHSA-7gcf-g7xr-8hxj : KeyValueMap serialization panics on empty sequence or map entries Bad or attacker controlled values could cause a panic while al
GHSA-7gcf-g7xr-8hxj: KeyValueMap serialization panics on empty sequence or map entries
Bad or attacker controlled values could cause a panic while allocating too large values.
Fixed in #966 by setting a maximum allocation size during the creation of collections like Vec or sets.
Thanks to @7thParkk for reporting the issue.
NoneAsZero adapter that maps Option<NonZero*> to a plain integer, encoding None as 0 by @SAY-5 (#486)Add support for base58 encoding, similar to the existing base64 setup by @mitinarseny
base58 encoding, similar to the existing base64 setup by @mitinarseny (#943)base64 with schemars support by @mitinarseny (#9949)Add support for hashbrown v0.17
Add support for hashbrown v0.17 (#940)
This extends the existing support for hashbrown to the newly released version.
Support OneOrMany with more sequence and set types
OneOrMany with more sequence and set types (#929)darling dependencySupport OneOrMany with smallvec v1 ( #920 , #922 )
Fix JsonSchemaAs of SetPreventDuplicates and SetLastValueWins . ( #906 , #907 )
Added support for smallvec v1 under the smallvec_1 feature flag by @isharma228
smallvec v1 under the smallvec_1 feature flag by @isharma228 (#895)JsonSchemaAs implementation for json::JsonString by @yogevm15 (#901)Fix building of the documentation by updating references to use serde_core .
serde_core.Added error inspection to VecSkipError and MapSkipError by @michelhe ( #878 ) This allows interacting with the previously hidden error, for example fo
Added error inspection to VecSkipError and MapSkipError by @michelhe (#878)
This allows interacting with the previously hidden error, for example for logging.
Checkout the newly added example to both types.
Allow documenting the types generated by serde_conv!.
The serde_conv! macro now acceps outer attributes before the optional visibility modifier.
This allow adding doc comments in the shape of #[doc = "..."] or any other attributes, such as lint modifiers.
serde_conv!(
#[doc = "Serialize bools as string"]
#[allow(dead_code)]
pub BoolAsString,
bool,
|x: &bool| ::std::string::ToString::to_string(x),
|x: ::std::string::String| x.parse()
);Add support for hashbrown v0.16 (#877)
This extends the existing support for hashbrown v0.14 and v0.15 to the newly released version.
toml dev-dependency.Show macro expansion in the docs.rs generated rustdoc. Since macros are used to generate trait implementations, this is useful to understand the exact
Add support for Range, RangeFrom, RangeTo, RangeInclusive (#851) RangeToInclusive is currently unsupported by serde.
Range, RangeFrom, RangeTo, RangeInclusive (#851)
RangeToInclusive is currently unsupported by serde.schemars implementations for Bound, Range, RangeFrom, RangeTo, RangeInclusive.schemars v1 under the schemars_1 feature flagAdded support for schemars v0.9.0 under the schemars_0_9 feature flag by @swlynch99
schemars v0.9.0 under the schemars_0_9 feature flag by @swlynch99 (#849)SerializeDisplayAlt derive macro (#833)
An alternative to the SerializeDisplay macro except instead of using the
plain formatting like format!("{}", ...), it serializes with the
Formatter::alternate flag set to true, like format!("{:#}", ...)serde_with::rust::unwrap_or_skip to support deserializing references by @beroal (#832)jsonschema dev-dependency.serde_conv available without the std feature by @arilou (#839)schemars v0.9.0 by @swlynch99 (#849)DurationSeconds types and other variants more accessible even without std (#845)Add with_suffix! macro, which puts a suffix on every struct field by @fgardt (#381/#797)
with_suffix! macro, which puts a suffix on every struct field by @fgardt (#381/#797)Cargo.toml files by @nyurik (#803)Add support for hashbrown v0.15 (#787/#790)
Add support for hashbrown v0.15 (#787/#790)
This extends the existing support for hashbrown v0.14 to the newly released version.
Add newline separator by @jayvdb
Add newline separator by @jayvdb (#777)
The UnixLineSeparator and DosLineSeparator can be used together with StringWithSeparator.
Proper handling of cfg_attr in the serde_as macro by @sivizius (#782)
This allows to parse more valid forms of the cfg_attr macro, including multiple values and attribute that do not follow the key = value schema.
Deserialize a map` and skip all elements failing to deserialize by @johnmave126
Deserialize a map` and skip all elements failing to deserialize by @johnmave126 (#763)
MapSkipError acts like a map (HashMap/BTreeMap), but keys or values that fail to deserialize, like are ignored.
For formats with heterogeneously typed maps, we can collect only the elements where both key and value are deserializable.
This is also useful in conjunction to #[serde(flatten)] to ignore some entries when capturing additional fields.
// JSON
"value": {"0": "v0", "5": "v5", "str": "str", "10": 2},
// Rust
#[serde_as(as = "MapSkipError<DisplayFromStr, _>")]
value: BTreeMap<u32, String>,
// Only deserializes entries with a numerical key and a string value, i.e.,
{0 => "v0", 5 => "v5"}
Fix compile issues when dependency schemars_0_8 is used with the preserve_order features
schemars_0_8 is used with the preserve_order features (#762)Bump MSRV to 1.67, since that is required for the time dependency. The time version needed to be updated for nightly compatibility.
time dependency.
The time version needed to be updated for nightly compatibility.JsonSchemaAs for OneOrMany instead of JsonSchema by @swlynch99 (#760)Do not emit schemars(deserialize_with = "...") annotations, as schemars does not support them (#735) Thanks to @sivizius for reporting the issue.
schemars(deserialize_with = "...") annotations, as schemars does not support them (#735)
Thanks to @sivizius for reporting the issue.Implement (De)Serialization for Pinned Smart Pointers by @Astralchroma
JsonSchemaAs for PickFirst by @swlynch99 (#721)base64 dependency to v0.22 (#724)serde_conv regressed and triggered clippy::ptr_arg and add test to prevent future problems. (#731)Implement JsonSchemaAs for EnumMap by @swlynch99
JsonSchemaAs for EnumMap by @swlynch99 (#697)JsonSchemaAs for IfIsHumanReadable by @swlynch99 (#717)JsonSchemaAs for KeyValueMap by @swlynch99 (#713)JsonSchemaAs for OneOrMany by @swlynch99 (#719)schema_with attributes on fields with schemars annotations by @swlynch99 (#715)
This extends the existing avoidance mechanism to a new variant fixing #712.Eliminate dependency on serde's "derive" feature by @dtolnay (#694) This allows parallel compilation of serde and serde_derive which can speed up the
serde and serde_derive which can speed up the wallclock time.
It requires that downstream crates do not use the "derive" feature either.Add IfIsHumanReadable for conditional implementation by @irriden (#690) Used to specify different transformations for text-based and binary formats.
IfIsHumanReadable for conditional implementation by @irriden (#690)
Used to specify different transformations for text-based and binary formats.JsonSchemaAs impls for all Duration* and Timestamp* adaptors by @swlynch99 (#685)regex dependency.The serde_as macro now better detects existing schemars attributes on fields and incorporates them (#682) This avoids errors on existing #[schemars(wi
serde_as macro now better detects existing schemars attributes on fields and incorporates them (#682)
This avoids errors on existing #[schemars(with = ...)] annotations.Support for schemars integration added by @swlynch99 (#666) The support uses a new Schema top-level item which implements JsonSchema The serde_as macr
schemars integration added by @swlynch99 (#666)
The support uses a new Schema top-level item which implements JsonSchema
The serde_as macro can now detect schemars usage and emits matching annotations for all fields with serde_as attribute.
Many types of this crate come already with support for the schemars, but support is not complete and will be extended over time.Lower minimum required serde version to 1.0.152 (#653) Thanks to @banool for submitting the PR.
Lower minimum required serde version to 1.0.152 (#653) Thanks to @banool for submitting the PR.
This allows people that have a problem with 1.0.153 to still use serde_with.
Add support for core::ops::Bound (#655)
Thanks to @qsantos for submitting the PR.
Support the hashbrown type HashMap and HashSet (#636, #637) Thanks to @OliverNChalk for raising the issue and submitting a PR.
Support the hashbrown type HashMap and HashSet (#636, #637)
Thanks to @OliverNChalk for raising the issue and submitting a PR.
This extends the existing support for HashMaps and HashSets to the hashbrown crate v0.14.
The same conversions as for the std and indexmap types are available, like general support for #[serde_as] and converting it to/from sequences or maps.
Generalize some trait bounds for DeserializeAs implementations
While working on #637, it came to light that some macros for generating DeserializeAs implementations were not as generic as they could.
This means they didn't work with custom hasher types, but only the default hashers.
This has now been fixed and custom hashers should work better, as long as they implement BuildHasher + Default.
(internal) Change how features are documented (#639)
This change moves the feature documentation into Cargo.toml in a format that can be read by lib.rs.
It will improve the generated features documentation there.
The page with all features remains in the guide but is now generated from the Cargo.toml information.
Add optional support for indexmap v2 (#621) Support for v1 is already available using the indexmap_1 feature. This adds identical support for v2 of in
indexmap_1 feature.
This adds identical support for v2 of indexmap using the indexmap_2 feature.i64::MIN using TimestampSeconds<i64> (#632, #633)
Thanks to @hollmmax for reporting and fixing the issue.Add FromIntoRef and TryFromIntoRef (#618) Thanks to @oblique for submitting the PR.
Add FromIntoRef and TryFromIntoRef (#618)
Thanks to @oblique for submitting the PR.
The new types are similar to the existing FromInto and TryFromInto types.
They behave different during serialization, allowing the removal of the Clone bound on their SerializeAs trait implementation
serde_as (#607)cfg_eval.Remove support for custom character sets. This is technically a breaking change. A code search on GitHub revealed no instances of anyone using that, a…
This breaking release should not impact most users. It only affects custom character sets used for base64 of which there are no instances of on GitHub.
Upgrade base64 to v0.21 (#543) Thanks to @jeff-hiner for submitting the PR.
Remove support for custom character sets.
This is technically a breaking change.
A code search on GitHub revealed no instances of anyone using that, and serde_with ships with many predefined character sets.
The removal means that future base64 upgrade will no longer be breaking changes.
Update syn to v2 and darling to v0.20 (#578) Update proc-macro dependencies. This change should have no impact on users, but now uses the same depende
syn to v2 and darling to v0.20 (#578)
Update proc-macro dependencies.
This change should have no impact on users, but now uses the same dependency as serde_derive.Improve the error message when deserializing OneOrMany or PickFirst fails. It now includes the original error message for each of the individual varia
Improve the error message when deserializing OneOrMany or PickFirst fails.
It now includes the original error message for each of the individual variants.
This is possible by dropping untagged enums as the internal implementations, since they will likely never support this, as these old PRs show serde#2376 and serde#1544.
The new errors look like:
OneOrMany could not deserialize any variant:
One: invalid type: map, expected u32
Many: invalid type: map, expected a sequence
PickFirst could not deserialize any variant:
First: invalid type: string "Abc", expected u32
Second: invalid digit found in string
Undo the changes to the trait bound for Seq. (#570, #571) The new implementation caused issues with serialization formats that require the sequence le
Undo the changes to the trait bound for Seq. (#570, #571)
The new implementation caused issues with serialization formats that require the sequence length beforehand.
It also caused problems such as that certain attributes which worked before no longer worked, due to a mismatching number of references.
Thanks to @stefunctional for reporting and for @stephaneyfx for providing a test case.
Add serde_as compatible versions for the existing duplicate key and value handling. (#534) The new types MapPreventDuplicates, MapFirstKeyWins, SetPre
Add serde_as compatible versions for the existing duplicate key and value handling. (#534)
The new types MapPreventDuplicates, MapFirstKeyWins, SetPreventDuplicates, and SetLastValueWins can replace the existing modules maps_duplicate_key_is_error, maps_first_key_wins, sets_duplicate_value_is_error, and sets_last_value_wins.
Added a new KeyValueMap type using the map key as a struct field. (#341)
This conversion is useful for maps, where an ID value is the map key, but the ID should become part of a single struct.
The conversion allows this, by using a special field named $key$.
This conversion is possible for structs and maps, using the $key$ field.
Tuples, tuple structs, and sequences are supported by turning the first value into the map key.
Each of the SimpleStructs
// Somewhere there is a collection:
// #[serde_as(as = "KeyValueMap<_>")]
// Vec<SimpleStruct>,
#[derive(Serialize, Deserialize)]
struct SimpleStruct {
b: bool,
// The field named `$key$` will become the map key
#[serde(rename = "$key$")]
id: String,
i: i32,
}
will turn into a JSON snippet like this.
"id-0000": {
"b": false,
"i": 123
},
Seq to allow for more custom types. (#565)
This extends the support beyond tuples.EnumMap passes the human_readable status of the Serializer to more places.alloc on targets without target_has_atomic = "ptr". (#560)
Thanks to @vembacher for reporting and fixing the issue.Add new Map and Seq types for converting between maps and tuple lists.
Add new Map and Seq types for converting between maps and tuple lists. (#527)
The behavior is not new, but already present using BTreeMap/HashMap or Vec.
However, the new types Map and Seq are also available on no_std, even without the alloc feature.
serde_with_macros dependency to the same version as the main crate.
This simplifies publishing and ensures a compatible version is always picked.serde_with::apply had an issue matching types when invisible token groups where in use (#538)
The token groups can stem from macro_rules expansion, but should be treated mostly transparent.
The old code required a group to match a group, while now groups are silently removed when checking for type patterns.Add new apply attribute to simplify repetitive attributes over many fields. Multiple rules and multiple attributes can be provided each.
Add new apply attribute to simplify repetitive attributes over many fields.
Multiple rules and multiple attributes can be provided each.
#[serde_with::apply(
Option => #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")],
Option<bool> => #[serde(rename = "bool")],
)]
#[derive(serde::Serialize)]
struct Data {
a: Option<String>,
b: Option<u64>,
c: Option<String>,
d: Option<bool>,
}
The apply attribute will expand into this, applying the attributes to the matching fields:
#[derive(serde::Serialize)]
struct Data {
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
a: Option<String>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
b: Option<u64>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
c: Option<String>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "bool")]
d: Option<bool>,
}
The attribute supports field matching using many rules, such as _ to apply to all fields and partial generics like Option to match any Option be it Option<String>, Option<bool>, or Option<T>.
The derive macros SerializeDisplay and DeserializeFromStr now take better care not to use conflicting names for generic values. (#526)
All used generics now start with __ to make conflicts with manually written code unlikely.
Thanks to @Elrendio for submitting a PR fixing the issue.
time added support for the well-known Iso8601 format. This extends the existing support of Rfc2822 and Rfc3339.
time added support for the well-known Iso8601 format.
This extends the existing support of Rfc2822 and Rfc3339.serde_as is used on an enum variant.
Attributes on enum variants were never supported.
But #[serde(with = "...")] can be added on variants, such that some confusion can occur when migration (#499).A cargo bug (cargo#10801) means that upgrading from v1 to v2 may add unnecessary crates to the Cargo.lock file.
A diff of the lock-file makes it seem that serde_with depends on new crates, even though these crates are unused and will not get compiled or linked.
However, tools consuming Cargo.lock or cargo metadata might give wrong results.
…annoyance (#183, #185, #311, #417). This is a breaking change, since now deserialization will pass where it did not before and this might be undesired…
Make JsonString<T> smarter by allowing nesting serde_as definitions.
This allows applying custom serialization logic before the value gets converted into a JSON string.
// Rust
#[serde_as(as = "JsonString<Vec<(JsonString, _)>>")]
value: BTreeMap<[u8; 2], u32>,
// JSON
{"value":"[[\"[1,2]\",3],[\"[4,5]\",6]]"}
Make #[serde_as] behave more intuitive on Option<T> fields.
The #[serde_as] macro now detects if a #[serde_as(as = "Option<S>")] is used on a field of type Option<T> and applies #[serde(default)] to the field.
This restores the ability to deserialize with missing fields and fixes a common annoyance (#183, #185, #311, #417).
This is a breaking change, since now deserialization will pass where it did not before and this might be undesired.
The Option field and transformation are detected by directly matching on the type name.
These variants are detected as Option.
Optionstd::option::Option, with or without leading ::core::option::Option, with or without leading ::If an existing default attribute is detected, the attribute is not applied again.
This behavior can be suppressed by using #[serde_as(no_default)] or #[serde_as(as = "Option<S>", no_default)].
NoneAsEmptyString and string_empty_as_none use a different serialization bound (#388).
Both types used AsRef<str> as the serialization bound.
This is limiting for non-string types like Option<i32>.
The deserialization often was already more flexible, due to the FromStr bound.
For most std types this should have little impact, as the types implementing AsRef<str> mostly implement Display, too, such as String, Cow<str>, or Rc<str>.
Bump MSRV to 1.60. This is required for the optional dependency feature syntax in cargo.
Remove old module-based conversions.
The newer serde_as based conversions are preferred.
seq_display_fromstr: Use DisplayFromStr in combination with your container type:
#[serde_as(as = "BTreeSet<DisplayFromStr>")]
addresses: BTreeSet<Ipv4Addr>,
#[serde_as(as = "Vec<DisplayFromStr>")]
bools: Vec<bool>,
tuple_list_as_map: Use BTreeMap on a Vec of tuples:
#[serde_as(as = "BTreeMap<_, _>")] // HashMap will also work
s: Vec<(i32, String)>,
map_as_tuple_list can be replaced with #[serde_as(as = "Vec<(_, _)>")].
display_fromstr can be replaced with #[serde_as(as = "DisplayFromStr")].
bytes_or_string can be replaced with #[serde_as(as = "BytesOrString")].
default_on_error can be replaced with #[serde_as(as = "DefaultOnError")].
default_on_null can be replaced with #[serde_as(as = "DefaultOnNull")].
string_empty_as_none can be replaced with #[serde_as(as = "NoneAsEmptyString")].
StringWithSeparator can now only be used in serde_as.
The definition of the Separator trait and its implementations have been moved to the formats module.
json::nested can be replaced with #[serde_as(as = "json::JsonString")].
Remove previously deprecated modules.
sets_first_value_winsbtreemap_as_tuple_list and hashmap_as_tuple_list can be replaced with #[serde_as(as = "Vec<(_, _)>")].A cargo bug (cargo#10801) means that upgrading from v1 to v2 may add unnecessary crates to the Cargo.lock file.
A diff of the lock-file makes it seem that serde_with depends on new crates, even though these crates are unused and will not get compiled or linked.
…annoyance (#183, #185, #311, #417). This is a breaking change, since now deserialization will pass where it did not before and this might be undesired…
Make #[serde_as] behave more intuitive on Option<T> fields.
The #[serde_as] macro now detects if a #[serde_as(as = "Option<S>")] is used on a field of type Option<T> and applies #[serde(default)] to the field.
This restores the ability to deserialize with missing fields and fixes a common annoyance (#183, #185, #311, #417).
This is a breaking change, since now deserialization will pass where it did not before and this might be undesired.
The Option field and transformation are detected by directly matching on the type name.
These variants are detected as Option.
Optionstd::option::Option, with or without leading ::core::option::Option, with or without leading ::If an existing default attribute is detected, the attribute is not applied again.
This behavior can be suppressed by using #[serde_as(no_default)] or #[serde_as(as = "Option<S>", no_default)].
NoneAsEmptyString and string_empty_as_none use a different serialization bound (#388).
Both types used AsRef<str> as the serialization bound.
This is limiting for non-string types like Option<i32>.
The deserialization often was already more flexible, due to the FromStr bound.
For most std types this should have little impact, as the types implementing AsRef<str> mostly implement Display, too, such as String, Cow<str>, or Rc<str>.
Bump MSRV to 1.60. This is required for the optional dependency feature syntax in cargo.
Remove old module-based conversions.
The newer serde_as based conversions are preferred.
seq_display_fromstr: Use DisplayFromStr in combination with your container type:
#[serde_as(as = "BTreeSet<DisplayFromStr>")]
addresses: BTreeSet<Ipv4Addr>,
#[serde_as(as = "Vec<DisplayFromStr>")]
bools: Vec<bool>,
tuple_list_as_map: Use BTreeMap on a Vec of tuples:
#[serde_as(as = "BTreeMap<_, _>")] // HashMap will also work
s: Vec<(i32, String)>,
map_as_tuple_list can be replaced with #[serde_as(as = "Vec<(_, _)>")].
display_fromstr can be replaced with #[serde_as(as = "DisplayFromStr")].
bytes_or_string can be replaced with #[serde_as(as = "BytesOrString")].
default_on_error can be replaced with #[serde_as(as = "DefaultOnError")].
default_on_null can be replaced with #[serde_as(as = "DefaultOnNull")].
string_empty_as_none can be replaced with #[serde_as(as = "NoneAsEmptyString")].
StringWithSeparator can now only be used in serde_as.
The definition of the Separator trait and its implementations have been moved to the formats module.
json::nested can be replaced with #[serde_as(as = "json::JsonString")].
Remove previously deprecated modules.
sets_first_value_winsbtreemap_as_tuple_list and hashmap_as_tuple_list can be replaced with #[serde_as(as = "Vec<(_, _)>")].Add support for time crate v0.3 #450
Add support for time crate v0.3 #450
time::Duration can now be serialized with the DurationSeconds and related converters.
// Rust
#[serde_as(as = "serde_with::DurationSeconds<u64>")]
value: Duration,
// JSON
"value": 86400,
time::OffsetDateTime and time::PrimitiveDateTime can now be serialized with the TimestampSeconds and related converters.
// Rust
#[serde_as(as = "serde_with::TimestampMicroSecondsWithFrac<String>")]
value: time::PrimitiveDateTime,
// JSON
"value": "1000000",
time::OffsetDateTime can be serialized in string format in different well-known formats.
Two formats are supported, time::format_description::well_known::Rfc2822 and time::format_description::well_known::Rfc3339.
// Rust
#[serde_as(as = "time::format_description::well_known::Rfc2822")]
rfc_2822: OffsetDateTime,
#[serde_as(as = "Vec<time::format_description::well_known::Rfc3339>")]
rfc_3339: Vec<OffsetDateTime>,
// JSON
"rfc_2822": "Fri, 21 Nov 1997 09:55:06 -0600",
"rfc_3339": ["1997-11-21T09:55:06-06:00"],
Deserialize bool from integers #456 462
Deserialize an integer and convert it into a bool.
BoolFromInt<Strict> (default) deserializes 0 to false and 1 to true, other numbers are errors.
BoolFromInt<Flexible> deserializes any non-zero as true.
Serialization only emits 0/1.
// Rust
#[serde_as(as = "BoolFromInt")] // BoolFromInt<Strict>
b: bool,
// JSON
"b": 1,
time requires that version.#[serde_as] and #[skip_serializing_none] attributes must always be places before #[derive].Added support for indexmap::IndexMap and indexmap::IndexSet types. #431, #436
Added support for indexmap::IndexMap and indexmap::IndexSet types. #431, #436
Both types are now compatible with these functions: maps_duplicate_key_is_error, maps_first_key_wins, sets_duplicate_value_is_error, sets_last_value_wins.
serde_as integration is provided by implementing both SerializeAs and DeserializeAs for both types.
IndexMaps can also be serialized as a list of types via the serde_as(as = "Vec<(_, _)>") annotation.
All implementations are gated behind the indexmap feature.
Thanks to @jgrund for providing parts of the implementation.
Depend on a newer serde_with_macros version to pull in some fixes.
serde_with_macros version to pull in some fixes.
SerializeDisplay and DeserializeFromStr #413Deserialize a Vec and skip all elements failing to deserialize #383
Deserialize a Vec and skip all elements failing to deserialize #383
VecSkipError acts like a Vec, but elements which fail to deserialize, like the "Yellow" are ignored.
#[derive(serde::Deserialize)]
enum Color {
Red,
Green,
Blue,
}
// JSON
"colors": ["Blue", "Yellow", "Green"],
// Rust
#[serde_as(as = "VecSkipError<_>")]
colors: Vec<Color>,
// => vec![Blue, Green]
Thanks to @hdhoang for creating the PR.
Transform between maps and Vec<Enum> #375
The new EnumMap type converts Vec of enums into a single map.
The key is the enum variant name, and the value is the variant value.
// Rust
VecEnumValues(vec![
EnumValue::Int(123),
EnumValue::String("Foo".to_string()),
EnumValue::Unit,
EnumValue::Tuple(1, "Bar".to_string()),
EnumValue::Struct {
a: 666,
b: "Baz".to_string(),
},
]
// JSON
{
"Int": 123,
"String": "Foo",
"Unit": null,
"Tuple": [
1,
"Bar",
],
"Struct": {
"a": 666,
"b": "Baz",
}
}
Timestamp*Seconds and Timestamp*SecondsWithFrac types can now be used with chrono::NaiveDateTime. #389Serialize bytes as base64 encoded strings. The character set and padding behavior can be configured.
Serialize bytes as base64 encoded strings.
The character set and padding behavior can be configured.
// Rust
#[serde_as(as = "serde_with::base64::Base64")]
value: Vec<u8>,
#[serde_as(as = "Base64<Bcrypt, Unpadded>")]
bcrypt_unpadded: Vec<u8>,
// JSON
"value": "SGVsbG8gV29ybGQ=",
"bcrypt_unpadded": "QETqZE6eT07wZEO",
The minimal supported Rust version (MSRV) is now specified in the Cargo.toml via the rust-version field. The field is supported in Rust 1.56 and has no effect on versions before.
More details: https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-rust-version-field
time v0.1 dependency, but changing the feature flags of the chrono dependency. This should not change anything. Crates requiring the oldtime feature of chrono can enable it separately.HashSets with custom hashers to be deserialized when used in combination with serde_as. #408Add BorrowCow which instructs serde to borrow data during deserialization of Cow<'_, str>, Cow<'_, [u8]>, or Cow<'_, [u8; N]>. (#347) The implementati
Add BorrowCow which instructs serde to borrow data during deserialization of Cow<'_, str>, Cow<'_, [u8]>, or Cow<'_, [u8; N]>. (#347)
The implementation is for serde#2072 and serde#2016, about #[serde(borrow)] not working for Option<Cow<'a, str>>.
#[serde_as]
#[derive(Deserialize, Serialize)]
struct Data<'a> {
#[serde_as(as = "Option<[BorrowCow; 1]>")]
nested: Option<[Cow<'a, str>; 1]>,
}
The #[serde(borrow)] annotation is automatically added by the #[serde_as] attribute.
bitflags requires that version now.flattened_maybe! no longer requires the serde_with crate to be available with a specific name.
This allows renaming the crate or using flattened_maybe! through a re-export without any complications.with_prefix! now supports an optional visibility modifier. (#327, #328) If not specified pub(self) is assumed.
with_prefix! now supports an optional visibility modifier. (#327, #328)
If not specified pub(self) is assumed.
with_prefix!(prefix_active "active_"); // => mod {...}
with_prefix!(pub prefix_active "active_"); // => pub mod {...}
with_prefix!(pub(crate) prefix_active "active_"); // => pub(crate) mod {...}
with_prefix!(pub(in other_mod) prefix_active "active_"); // => pub(in other_mod) mod {...}
Thanks to @elpiel for raising and fixing the issue.
The Bytes type now supports borrowed and Cow arrays of fixed size (requires Rust 1.51+)
The Bytes type now supports borrowed and Cow arrays of fixed size (requires Rust 1.51+)
#[serde_as(as = "Bytes")]
#[serde(borrow)]
borrowed_array: &'a [u8; 15],
#[serde_as(as = "Bytes")]
#[serde(borrow)]
cow_array: Cow<'a, [u8; 15]>,
Note: For borrowed arrays, the used Deserializer needs to support Serde's 0-copy deserialization.
Suppress clippy warnings, which can occur while using serde_conv (#320) Thanks to @mkroening for reporting and fixing the issue.
serde_conv (#320)
Thanks to @mkroening for reporting and fixing the issue.NoneAsEmptyString: Deserialize using FromStr instead of using for<'a> From<&'a str> (#316) This will *not* change any behavior when applied to a field
NoneAsEmptyString: Deserialize using FromStr instead of using for<'a> From<&'a str> (#316)
This will not change any behavior when applied to a field of type Option<String> as used in the documentation.
Thanks to @mkroening for finding and fixing the issue.Added FromInto and TryFromInto adapters, which enable serialization by converting into a proxy type.
Added FromInto and TryFromInto adapters, which enable serialization by converting into a proxy type.
// Rust
#[serde_as(as = "FromInto<(u8, u8, u8)>")]
value: Rgb,
impl From<(u8, u8, u8)> for Rgb { ... }
impl From<Rgb> for (u8, u8, u8) { ... }
// JSON
"value": [128, 64, 32],
New serde_conv! macro to create conversion types with reduced boilerplate.
The generated types can be used with #[serde_as] or serde's with-attribute.
serde_with::serde_conv!(
RgbAsArray,
Rgb,
|rgb: &Rgb| [rgb.red, rgb.green, rgb.blue],
|value: [u8; 3]| -> Result<_, std::convert::Infallible> {
Ok(Rgb {
red: value[0],
green: value[1],
blue: value[2],
})
}
);
The hex::Hex type also works for u8-arrays on Rust 1.48. Thanks to @TheAlgorythm for raising and fixing the issue.
hex::Hex type also works for u8-arrays on Rust 1.48.
Thanks to @TheAlgorythm for raising and fixing the issue.The old names continue to exist but are marked as deprecated.
Added PickFirst adapter for serde_as. #291
It allows deserializing from multiple different forms.
Deserializing a number from either a number or string can be implemented like:
#[serde_as(as = "PickFirst<(_, DisplayFromStr)>")]
value: u32,
Implement SerializeAs/DeserializeAs for more wrapper types. #288, #293
This now supports:
Arc, sync::WeakRc, rc::WeakCell, RefCellMutex, RwLockResultserde_with::rust::map_as_tuple_list module as a replacement for serde_with::rust::btreemap_as_tuple_list and serde_with::rust::hashmap_as_tuple_list.
The new module uses IntoIterator and FromIterator as trait bound making it usable in more situations.
The old names continue to exist but are marked as deprecated.serde_with::rust::btreemap_as_tuple_list and serde_with::rust::hashmap_as_tuple_list.
You can use serde_with::rust::map_as_tuple_list as a replacement.Add support for arrays of arbitrary size. ([#272]) This feature requires Rust 1.51+.
Add support for arrays of arbitrary size. (#272) This feature requires Rust 1.51+.
// Rust
#[serde_as(as = "[[_; 64]; 33]")]
value: [[u8; 64]; 33],
// JSON
"value": [[0,0,0,0,0,...], [0,0,0,...], ...],
Mapping of arrays was available before, but limited to arrays of length 32. All conversion methods are available for the array elements.
This is similar to the existing serde-big-array crate with three important improvements:
serde_as annotation.Arrays with tuple elements can now be deserialized from a map. (#272) This feature requires Rust 1.51+.
// Rust
#[serde_as(as = "BTreeMap<_, _>")]
value: [(String, u16); 3],
// JSON
"value": {
"a": 1,
"b": 2,
"c": 3
},
The Bytes type is heavily inspired by serde_bytes and ports it to the serde_as system. (#277)
#[serde_as(as = "Bytes")]
value: Vec<u8>,
Compared to serde_bytes these improvements are available
serde_as annotation (see serde-bytes#14).The OneOrMany type allows deserializing a Vec from either a single element or a sequence. (#281)
#[serde_as(as = "OneOrMany<_>")]
cities: Vec<String>,
This allows deserializing from either cities: "Berlin" or cities: ["Berlin", "Paris"].
The serialization can be configured to always emit a list with PreferMany or emit a single element with PreferOne.
Fix compiling when having a struct field without the serde_as annotation by updating serde_with_macros. This broke in 1.4.0 of serde_with_macros. #267
serde_as annotation by updating serde_with_macros.
This broke in 1.4.0 of serde_with_macros. #267Bump macro crate dependency (serde_with_macros) to 1.4.0 to pull in those improvements.
serde_with_macros) to 1.4.0 to pull in those improvements.New function serde_with::deserialize_ignore_any. This function allows deserializing any data and returns the default value of the type. This can be us
New function serde_with::rust::deserialize_ignore_any.
This function allows deserializing any data and returns the default value of the type.
This can be used in conjunction with #[serde(other)] to allow deserialization of unknown data carrying enum variants.
Thanks to @lovasoa for suggesting and implementing it.
Add new types similar to DurationSeconds and TimestampSeconds but for base units of milliseconds, microseconds, and nanoseconds. The *WithFrac variant
DurationSeconds and TimestampSeconds but for base units of milliseconds, microseconds, and nanoseconds.
The *WithFrac variants also exist.SerializeAs implementation for references.Sized trait bound from As, Same, SerializeAs, and SerializeAsWrap.
Only the serialize part is relaxed.Your coding agent can read these notes before it upgrades. Set up the MCP server →