serde_ignored_fields/lib.rs
1//! De-serialize and re-serialize a type while preserving ignored fields.
2//!
3//! Sometimes you may wish to preserve the ignored fields of something you are deserializing.
4//! If you are in controll of the type, you could make use of the `#[serde(flatten)]` attribute:
5//! ```
6//! # fn main() -> Result<(), Box<dyn std::error::Error>>{
7//! # use assert2::assert;
8//! #
9//! #[derive(serde::Deserialize, serde::Serialize)]
10//! struct Thing {
11//! name: String,
12//!
13//! #[serde(flatten)]
14//! extra_fields: serde_yaml::Mapping,
15//! }
16//! #
17//! # let thing: Thing = serde_yaml::from_str("
18//! # name: Turbo Encabulator
19//! # base_plate:
20//! # prefabulated: true
21//! # material: aluminite
22//! # casing: malleable logarithmic
23//! # ")?;
24//! #
25//! # assert!(thing.name == "Turbo Encabulator");
26//! # assert!(thing.extra_fields["base_plate"]["prefabulated"] == true);
27//! # assert!(thing.extra_fields["base_plate"]["material"] == "aluminite");
28//! # assert!(thing.extra_fields["casing"] == "malleable logarithmic");
29//! # Ok(())
30//! # }
31//! ```
32//!
33//! This crate can help you if you are *not* in control of the type.
34//! You can wrap the type in [`PreserveIgnoredFields`]:
35//!
36//! ```
37//! # fn main() -> Result<(), Box<dyn std::error::Error>>{
38//! # use assert2::assert;
39//! use serde_ignored_fields::PreserveIgnoredFields;
40//!
41//! #[derive(serde::Deserialize, serde::Serialize)]
42//! struct Thing {
43//! name: String,
44//! }
45//!
46//! let thing: PreserveIgnoredFields<Thing, serde_yaml::Mapping> = serde_yaml::from_str("
47//! name: Turbo Encabulator
48//! base_plate:
49//! prefabulated: true
50//! material: aluminite
51//! casing: malleable logarithmic
52//! ")?;
53//!
54//! assert!(thing.value.name == "Turbo Encabulator");
55//! assert!(thing.ignored_fields["base_plate"]["prefabulated"] == true);
56//! assert!(thing.ignored_fields["base_plate"]["material"] == "aluminite");
57//! assert!(thing.ignored_fields["casing"] == "malleable logarithmic");
58//! # Ok(())
59//! # }
60//! ```
61//!
62//! If you enable the `schemars` feature, [`PreserveIgnoredFields<T, U>`] implements the [`schemars::JsonSchema`] trait.
63//! It forwards directly to the [`schemars::JsonSchema`] implementation of `T`.
64//!
65//! # Limitations
66//! Because `serde` does not provide first class support for capturing ignored fields, there are some limitations.
67//!
68//! ## Self-describing format
69//! First, [`PreserveIgnoredFields`] only works with a self-describing format such as JSON, YAML or TOML.
70//! This should not come as a surprise, and will not be a real limitation in practise
71//! (how can you have ignored fields if the data format doesn't tell you what the fields are?).
72//!
73//! In [`serde`] terms: the [`serde::Deserializer`] must support [`serde::Deserializer::deserialize_any()`].
74//!
75//! ## Serialize/Deserialize implementations
76//! Secondly, the type `T` being (de)serialized must be represented as a key/value map,
77//! and it must call [`serde::Deserializer::deserialize_ignored_any()`] to deserialize ignored fields.
78//! It must not produce an error when encountering an unknown field (so the type must not use `#[serde(deny_unknown_fields)]`).
79//!
80//! In particular, this means that it will not work for *externally* tagged enums, *internally* tagged enums and *untagged* enums.
81//! Externally tagged enums are not always serialized as key/value maps (the serialization format controls their layout).
82//! Internally and untagged enums have to look at fields before knowing which of the fields are actually going to be ignored.
83//! This crate *does* work with adjectently tagged enums.
84//!
85//! It also means that it will not work for types that first deserialize into something like [`serde_json::Value`] before processing the value further.
86//! When deserialized, the [`serde_json::Value`] uses all fields.
87//! The next processing step may discard them again, but there is no way for [`PreserveIgnoredFields`] to know about this.
88//!
89//! In summary:
90//! Using [`PreserveIgnoredFields`] with structs that use the standard serde derive macros from [`serde`] will work, as long as you did not use `#[serde(deny_unknown_fields)]`.
91//! Using it with enums that use the standard derive macros will only work if they are *adjectently tagged* (they have a serde `tag = "..."` *and* `content = "..."` attribute).
92
93#![warn(missing_docs)]
94#![warn(missing_debug_implementations)]
95#![cfg_attr(feature = "doc-cfg", feature(doc_cfg))]
96
97mod deserialize;
98mod features;
99mod key;
100mod serialize;
101
102/// Wrapper to preserve ignored fields.
103///
104/// The wrapped type is stored in the [value][Self::value] field.
105/// Ignored fields are stored in the [`ignored_fields`][Self::ignored_fields] field.
106///
107/// The `IgnoredFields` type has to implement [`DeserializeIgnoredFields`] for this type to implement [`serde::Deserialize`],
108/// and it has to implement [`SerializeIgnoredFields`] for this type to implement [`serde::Serialize`].
109///
110/// Be sure the read the [main library documentation](crate) about the limitations.
111///
112/// If you enable the `schemars` feature, this type implements the [`schemars::JsonSchema`] trait.
113/// The implementation forwards directly to the implementation of `T`.
114#[derive(Debug, Clone, Default, PartialEq)]
115pub struct PreserveIgnoredFields<T, U> {
116 /// The wrapped value.
117 pub value: T,
118
119 /// The ignored fields.
120 pub ignored_fields: U,
121}
122
123impl<T, U> PreserveIgnoredFields<T, U> {
124 /// Create a new [`PreserveIgnoredFields`] struct from a wrapped value and the ignored fields.
125 pub fn new(value: T, ignored_fields: U) -> Self {
126 Self { value, ignored_fields }
127 }
128}
129
130impl<T, U: Default> From<T> for PreserveIgnoredFields<T, U> {
131 fn from(value: T) -> Self {
132 Self::new(value, U::default())
133 }
134}
135
136/// Trait for types that can collect ignored fields during deserialization.
137pub trait DeserializeIgnoredFields<'de>: Default + std::fmt::Debug {
138 /// The type of the key for the ignored fields.
139 type Key: serde::Deserialize<'de>;
140
141 /// The type of the value of ignored fields.
142 type Value: serde::Deserialize<'de>;
143
144 /// Insert an ignored field.
145 fn insert<E: serde::de::Error>(&mut self, key: Self::Key, value: Self::Value) -> Result<(), E>;
146}
147
148/// Trait for types that can be used to re-serialize ignored fields.
149pub trait SerializeIgnoredFields {
150 /// The type of the key for the ignored fields.
151 type Key: ?Sized + serde::Serialize;
152
153 /// The type of the value of ignored fields.
154 type Value: ?Sized + serde::Serialize;
155
156 /// The amount of ignored fields.
157 fn len(&self) -> usize;
158
159 /// Check if there are exactly 0 ignored fields.
160 fn is_empty(&self) -> bool {
161 self.len() == 0
162 }
163
164 /// Iterate over the ignored fields.
165 fn iter(&self) -> impl Iterator<Item = (&Self::Key, &Self::Value)>;
166}