Skip to main content

json_serde/
lib.rs

1// Copyright 2026 Oxide Computer Company
2
3#![doc = include_str!("../README.md")]
4
5// Alias the crate under its external name so the unit tests can use the
6// documented attribute recipes verbatim.
7#[cfg(test)]
8extern crate self as json_serde;
9
10use serde_core::{
11    Deserialize, Deserializer, Serializer,
12    de::Error,
13    ser::{Impossible, SerializeSeq},
14};
15
16/// Deserializer function that always produces `Some(T)` if a value is present.
17///
18/// It is useful when one wants to distinguish between a field that's absent
19/// and a field that's present with a `null` value. For example, the annotation
20/// below may be used for a field that may be absent, but may not be `null`.
21///
22/// ```
23/// # #[derive(serde::Deserialize, serde::Serialize)]
24/// # struct Foo {
25///     #[serde(
26///         default,
27///         deserialize_with = "::json_serde::deserialize_some",
28///         skip_serializing_if = "Option::is_none",
29///     )]
30///     field: Option<String>,
31/// # }
32/// ```
33///
34/// It can also be used with a "double-Option" to determine whether a field
35/// was absent, `null`, or had a value:
36/// ```
37/// # #[derive(serde::Deserialize, serde::Serialize)]
38/// # struct Foo {
39///     #[serde(
40///         default,
41///         deserialize_with = "::json_serde::deserialize_some",
42///         skip_serializing_if = "Option::is_none",
43///     )]
44///     field: Option<Option<String>>,
45/// # }
46/// ```
47///
48/// In the first case, a `null` value results in an error because a `String`
49/// cannot be deserialized from `null`. In the second case, a `null` value
50/// results in `field` having a value of `Some(None)` since `Option<String>`
51/// *can* be deserialized from `null`.
52pub fn deserialize_some<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
53where
54    D: Deserializer<'de>,
55    T: Deserialize<'de>,
56{
57    T::deserialize(deserializer).map(Some)
58}
59
60/// Serializer used to flatten sequences into other sequences.
61///
62/// Wrap an in-progress [`SerializeSeq`] and serialize a sequence-shaped
63/// value into the wrapper: the value's elements are appended to the
64/// enclosing sequence. Values that do not serialize as a sequence are an
65/// error. Ending the flattened sequence leaves the enclosing serializer
66/// open for further elements.
67///
68/// The value must serialize as a serde *seq* (e.g. `Vec<T>`); fixed-size
69/// tuples and arrays serialize via `serialize_tuple` and are rejected.
70pub struct FlattenedSequenceSerializer<'a, S>(&'a mut S);
71
72impl<'a, S> FlattenedSequenceSerializer<'a, S>
73where
74    S: serde_core::ser::SerializeSeq,
75{
76    pub fn new(seq_serializer: &'a mut S) -> Self {
77        Self(seq_serializer)
78    }
79
80    fn wrong_type_error<T>() -> Result<T, S::Error> {
81        Err(serde_core::ser::Error::custom(
82            "FlattenedSequenceSerializer only supports sequence values",
83        ))
84    }
85}
86
87impl<'a, S> Serializer for FlattenedSequenceSerializer<'a, S>
88where
89    S: serde_core::ser::SerializeSeq,
90{
91    type Ok = ();
92    type Error = S::Error;
93
94    type SerializeSeq = Self;
95    type SerializeTuple = Impossible<Self::Ok, Self::Error>;
96    type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
97    type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
98    type SerializeMap = serde_core::ser::Impossible<Self::Ok, Self::Error>;
99    type SerializeStruct = serde_core::ser::Impossible<Self::Ok, Self::Error>;
100    type SerializeStructVariant = serde_core::ser::Impossible<Self::Ok, Self::Error>;
101
102    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
103        Ok(self)
104    }
105
106    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
107        Self::wrong_type_error()
108    }
109
110    fn serialize_tuple_struct(
111        self,
112        _name: &'static str,
113        _len: usize,
114    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
115        Self::wrong_type_error()
116    }
117
118    fn serialize_tuple_variant(
119        self,
120        _name: &'static str,
121        _variant_index: u32,
122        _variant: &'static str,
123        _len: usize,
124    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
125        Self::wrong_type_error()
126    }
127
128    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
129        Err(serde_core::ser::Error::custom(
130            "FlattenedSequenceSerializer does not support maps",
131        ))
132    }
133
134    fn serialize_struct(
135        self,
136        _name: &'static str,
137        _len: usize,
138    ) -> Result<Self::SerializeStruct, Self::Error> {
139        Err(serde_core::ser::Error::custom(
140            "FlattenedSequenceSerializer does not support structs",
141        ))
142    }
143
144    fn serialize_struct_variant(
145        self,
146        _name: &'static str,
147        _variant_index: u32,
148        _variant: &'static str,
149        _len: usize,
150    ) -> Result<Self::SerializeStructVariant, Self::Error> {
151        Err(serde_core::ser::Error::custom(
152            "FlattenedSequenceSerializer does not support struct variants",
153        ))
154    }
155
156    fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
157        Self::wrong_type_error()
158    }
159
160    fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
161        Self::wrong_type_error()
162    }
163
164    fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
165        Self::wrong_type_error()
166    }
167
168    fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
169        Self::wrong_type_error()
170    }
171
172    fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
173        Self::wrong_type_error()
174    }
175
176    fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
177        Self::wrong_type_error()
178    }
179
180    fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
181        Self::wrong_type_error()
182    }
183
184    fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
185        Self::wrong_type_error()
186    }
187
188    fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
189        Self::wrong_type_error()
190    }
191
192    fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
193        Self::wrong_type_error()
194    }
195
196    fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
197        Self::wrong_type_error()
198    }
199
200    fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
201        Self::wrong_type_error()
202    }
203
204    fn serialize_str(self, _v: &str) -> Result<Self::Ok, Self::Error> {
205        Self::wrong_type_error()
206    }
207
208    fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
209        Self::wrong_type_error()
210    }
211
212    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
213        Self::wrong_type_error()
214    }
215
216    fn serialize_some<T>(self, _value: &T) -> Result<Self::Ok, Self::Error>
217    where
218        T: ?Sized + serde_core::Serialize,
219    {
220        Self::wrong_type_error()
221    }
222
223    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
224        Self::wrong_type_error()
225    }
226
227    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
228        Self::wrong_type_error()
229    }
230
231    fn serialize_unit_variant(
232        self,
233        _name: &'static str,
234        _variant_index: u32,
235        _variant: &'static str,
236    ) -> Result<Self::Ok, Self::Error> {
237        Self::wrong_type_error()
238    }
239
240    fn serialize_newtype_struct<T>(
241        self,
242        _name: &'static str,
243        _value: &T,
244    ) -> Result<Self::Ok, Self::Error>
245    where
246        T: ?Sized + serde_core::Serialize,
247    {
248        Self::wrong_type_error()
249    }
250
251    fn serialize_newtype_variant<T>(
252        self,
253        _name: &'static str,
254        _variant_index: u32,
255        _variant: &'static str,
256        _value: &T,
257    ) -> Result<Self::Ok, Self::Error>
258    where
259        T: ?Sized + serde_core::Serialize,
260    {
261        Self::wrong_type_error()
262    }
263}
264
265impl<'a, S> SerializeSeq for FlattenedSequenceSerializer<'a, S>
266where
267    S: serde_core::ser::SerializeSeq,
268{
269    type Ok = ();
270
271    type Error = S::Error;
272
273    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
274    where
275        T: ?Sized + serde_core::Serialize,
276    {
277        self.0.serialize_element(value)
278    }
279
280    fn end(self) -> Result<Self::Ok, Self::Error> {
281        Ok(())
282    }
283}
284
285/// Deserializer used to extract flattened sequences from the end of another
286/// sequence.
287///
288/// Wrap an in-progress [`SeqAccess`](serde_core::de::SeqAccess) and
289/// deserialize a sequence-shaped value from the wrapper: the value
290/// consumes the remaining elements of the enclosing sequence. Target
291/// types that do not expect a sequence are an error.
292///
293/// The target must deserialize as a serde *seq* (e.g. `Vec<T>`);
294/// fixed-size tuples and arrays deserialize via `deserialize_tuple` and
295/// are rejected.
296pub struct FlattenedSequenceDeserializer<'a, S>(&'a mut S);
297
298impl<'a, S> FlattenedSequenceDeserializer<'a, S> {
299    pub fn new(seq_access: &'a mut S) -> Self {
300        Self(seq_access)
301    }
302}
303
304impl<'de, 'a, S> Deserializer<'de> for FlattenedSequenceDeserializer<'a, S>
305where
306    S: serde_core::de::SeqAccess<'de>,
307{
308    type Error = S::Error;
309
310    fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, S::Error>
311    where
312        V: serde_core::de::Visitor<'de>,
313    {
314        Err(S::Error::custom("type must expect a sequence"))
315    }
316
317    serde_core::forward_to_deserialize_any! {
318        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
319        bytes byte_buf option unit unit_struct newtype_struct tuple
320        tuple_struct map struct enum identifier ignored_any
321    }
322
323    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
324    where
325        V: serde_core::de::Visitor<'de>,
326    {
327        visitor.visit_seq(self.0)
328    }
329}
330
331/// Always returns `true`; a predicate for `#[serde(skip_serializing_if)]`.
332///
333/// Use `#[serde(skip_serializing_if = "::json_serde::always")]` in place of
334/// `#[serde(skip_serializing)]` on fields that must never serialize when
335/// the containing type also derives the schemars 0.8 `JsonSchema`: schemars
336/// 0.8 (through 0.8.22) incorrectly marks `default` + `skip_serializing`
337/// fields as required in the generated schema, while conditionally-skipped
338/// fields are correctly optional. The two attribute forms serialize
339/// identically. See [`Absent`].
340pub fn always<T>(_: &T) -> bool {
341    true
342}
343
344/// Type for a value that *must* be absent.
345///
346/// This should be accompanied by serde attributes to indicate that:
347/// - the default value should be taken `#[serde(default)]`
348/// - it should never be serialized `#[serde(skip_serializing)]` (or
349///   `#[serde(skip_serializing_if = "::json_serde::always")]`; see
350///   [`always`])
351///
352/// Deserialization always fails--the field must not be present--and
353/// serialization fails if it is ever invoked, hence the attributes above.
354/// With the `schemars08` and `schemars1` features, `Absent`'s `JsonSchema`
355/// implementation is the `false` schema, which no value satisfies.
356#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
357pub struct Absent;
358
359impl serde_core::Serialize for Absent {
360    fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
361    where
362        S: Serializer,
363    {
364        use serde_core::ser::Error;
365        Err(S::Error::custom(
366            "field must be annotated with `skip_serializing` (or \
367             `skip_serializing_if = \"json_serde::always\"`)",
368        ))
369    }
370}
371
372impl<'de> Deserialize<'de> for Absent {
373    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
374    where
375        D: Deserializer<'de>,
376    {
377        use serde_core::de::Error;
378        // Chew up any inputs.
379        let _ = serde_core::de::IgnoredAny::deserialize(deserializer)?;
380        Err(D::Error::custom("field must be absent"))
381    }
382}
383
384#[cfg(feature = "schemars08")]
385impl schemars08::JsonSchema for Absent {
386    fn schema_name() -> String {
387        "Absent".to_string()
388    }
389
390    fn json_schema(_: &mut schemars08::r#gen::SchemaGenerator) -> schemars08::schema::Schema {
391        schemars08::schema::Schema::Bool(false)
392    }
393
394    fn is_referenceable() -> bool {
395        false
396    }
397}
398
399#[cfg(feature = "schemars1")]
400impl schemars1::JsonSchema for Absent {
401    fn schema_name() -> std::borrow::Cow<'static, str> {
402        std::borrow::Cow::Borrowed("Absent")
403    }
404
405    fn json_schema(_: &mut schemars1::SchemaGenerator) -> schemars1::Schema {
406        schemars1::Schema::from(false)
407    }
408
409    fn inline_schema() -> bool {
410        true
411    }
412}
413
414#[cfg(test)]
415mod tests {
416    use serde::{Deserialize, Serialize, ser::SerializeSeq};
417
418    use crate::{Absent, FlattenedSequenceDeserializer, FlattenedSequenceSerializer};
419
420    #[test]
421    fn test_deserialize_some() {
422        #[derive(Debug, PartialEq, Serialize, Deserialize)]
423        struct Test {
424            #[serde(
425                default,
426                deserialize_with = "::json_serde::deserialize_some",
427                skip_serializing_if = "Option::is_none"
428            )]
429            field: Option<String>,
430        }
431
432        // An absent field yields None.
433        let de = serde_json::from_str::<Test>("{}").unwrap();
434        assert_eq!(de.field, None);
435
436        // A null value is an error: a String cannot be deserialized from
437        // null.
438        assert!(serde_json::from_str::<Test>(r#"{ "field": null }"#).is_err());
439
440        // A present value yields Some.
441        let de = serde_json::from_str::<Test>(r#"{ "field": "value" }"#).unwrap();
442        assert_eq!(de.field, Some("value".to_string()));
443    }
444
445    #[test]
446    fn test_deserialize_some_double_option() {
447        #[derive(Debug, PartialEq, Serialize, Deserialize)]
448        struct Test {
449            #[serde(
450                default,
451                deserialize_with = "::json_serde::deserialize_some",
452                skip_serializing_if = "Option::is_none"
453            )]
454            field: Option<Option<String>>,
455        }
456
457        // An absent field yields None.
458        let de = serde_json::from_str::<Test>("{}").unwrap();
459        assert_eq!(de.field, None);
460
461        // A null value yields Some(None).
462        let de = serde_json::from_str::<Test>(r#"{ "field": null }"#).unwrap();
463        assert_eq!(de.field, Some(None));
464
465        // A present value yields Some(Some(..)).
466        let de = serde_json::from_str::<Test>(r#"{ "field": "value" }"#).unwrap();
467        assert_eq!(de.field, Some(Some("value".to_string())));
468    }
469
470    #[test]
471    fn flatten_tuple_vec() {
472        #[derive(Debug, Eq, PartialEq)]
473        struct TestType(u32, String, Vec<u32>);
474
475        impl Serialize for TestType {
476            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
477            where
478                S: serde::Serializer,
479            {
480                let mut seq = serializer.serialize_seq(None)?;
481
482                seq.serialize_element(&self.0)?;
483                seq.serialize_element(&self.1)?;
484
485                self.2
486                    .serialize(FlattenedSequenceSerializer::new(&mut seq))?;
487
488                seq.end()
489            }
490        }
491
492        impl<'de> Deserialize<'de> for TestType {
493            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
494            where
495                D: serde::Deserializer<'de>,
496            {
497                struct Visitor;
498                impl<'de> serde::de::Visitor<'de> for Visitor {
499                    type Value = TestType;
500
501                    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
502                        formatter.write_str("a flattened tuple vec")
503                    }
504
505                    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
506                    where
507                        A: serde::de::SeqAccess<'de>,
508                    {
509                        let v_0 = seq.next_element()?.ok_or_else(|| {
510                            serde::de::Error::invalid_length(0, &"a tuple of size 2")
511                        })?;
512                        let v_1 = seq.next_element()?.ok_or_else(|| {
513                            serde::de::Error::invalid_length(1, &"a tuple of size 2")
514                        })?;
515
516                        let rest =
517                            Deserialize::deserialize(FlattenedSequenceDeserializer::new(&mut seq))?;
518
519                        Ok(TestType(v_0, v_1, rest))
520                    }
521                }
522                deserializer.deserialize_seq(Visitor)
523            }
524        }
525
526        let value = TestType(42, "Hello".to_string(), vec![1, 2, 3]);
527        let serialized = serde_json::to_string(&value).unwrap();
528
529        assert_eq!(serialized, "[42,\"Hello\",1,2,3]");
530
531        let de_value = serde_json::from_str::<TestType>(&serialized).unwrap();
532
533        assert_eq!(value, de_value);
534
535        let value = TestType(7, "World".to_string(), vec![]);
536        let serialized = serde_json::to_string(&value).unwrap();
537
538        assert_eq!(serialized, "[7,\"World\"]");
539
540        let de_value = serde_json::from_str::<TestType>(&serialized).unwrap();
541
542        assert_eq!(value, de_value);
543
544        let input = "[1, \"Two\", \"Three\", 4, 5, 6]";
545        let de_result = serde_json::from_str::<TestType>(input);
546        assert!(de_result.is_err());
547
548        let input = "[100]";
549        let de_result = serde_json::from_str::<TestType>(input);
550        let e = de_result.unwrap_err().to_string();
551        assert!(
552            e.starts_with("invalid length 1, expected a tuple of size 2"),
553            "{e}",
554        );
555
556        let input = "[1, \"Two\", \"Three\"]";
557        let de_result = serde_json::from_str::<TestType>(input);
558        let e = de_result.unwrap_err().to_string();
559        assert!(e.starts_with("invalid type"), "{e}",);
560    }
561
562    #[test]
563    fn test_absent() {
564        #[derive(Serialize, Deserialize)]
565        struct Test {
566            #[serde(default, skip_serializing)]
567            absent: Absent,
568        }
569
570        let test = Test { absent: Absent };
571
572        assert_eq!(serde_json::to_string(&test).unwrap(), "{}");
573
574        let de = serde_json::from_str::<Test>("{}").unwrap();
575        let Absent = de.absent;
576        assert!(serde_json::from_str::<Test>(r#"{ "absent": null }"#).is_err());
577    }
578
579    #[cfg(feature = "schemars08")]
580    #[test]
581    fn test_absent_schema() {
582        // The `always` helper is necessary due to a bug present in schemars
583        // 0.8.22 where default + skip_serializing yields a required
584        // property. It is fixed in schemars 1.x.
585        #[derive(Serialize, Deserialize, schemars08::JsonSchema)]
586        #[schemars(crate = "schemars08")]
587        struct Test {
588            #[serde(skip_serializing_if = "crate::always")]
589            #[serde(default)]
590            absent: Absent,
591        }
592
593        let test = Test { absent: Absent };
594
595        assert_eq!(serde_json::to_string(&test).unwrap(), "{}");
596
597        assert!(serde_json::from_str::<Test>(r#"{ "absent": null }"#).is_err());
598
599        let schema = schemars08::schema_for!(Test);
600        let expected = serde_json::json!({
601            "$schema": "http://json-schema.org/draft-07/schema#",
602            "title": "Test",
603            "type": "object",
604            "properties": {
605                "absent": false
606            }
607        });
608
609        assert_eq!(serde_json::to_value(&schema).unwrap(), expected);
610    }
611
612    #[cfg(feature = "schemars1")]
613    #[test]
614    fn test_absent_schema_v1() {
615        // Unlike schemars 0.8.22, schemars 1.x correctly treats default +
616        // skip_serializing as an optional property, so no workaround akin to
617        // the `always` helper is needed here.
618        #[derive(Serialize, Deserialize, schemars1::JsonSchema)]
619        #[schemars(crate = "schemars1")]
620        struct Test {
621            #[serde(default, skip_serializing)]
622            absent: Absent,
623        }
624
625        let test = Test { absent: Absent };
626
627        assert_eq!(serde_json::to_string(&test).unwrap(), "{}");
628
629        let de = serde_json::from_str::<Test>("{}").unwrap();
630        let Absent = de.absent;
631        assert!(serde_json::from_str::<Test>(r#"{ "absent": null }"#).is_err());
632
633        let schema = schemars1::schema_for!(Test);
634        // schemars 1.x marks skip_serializing fields as `writeOnly`; to
635        // attach that keyword it rewrites the `false` schema as its object
636        // form, `{"not": {}}`, which is equivalent.
637        let expected = serde_json::json!({
638            "$schema": "https://json-schema.org/draft/2020-12/schema",
639            "title": "Test",
640            "type": "object",
641            "properties": {
642                "absent": {
643                    "not": {},
644                    "writeOnly": true
645                }
646            }
647        });
648
649        assert_eq!(serde_json::to_value(&schema).unwrap(), expected);
650    }
651}