schemars/
ser.rs

1use crate::schema::*;
2use crate::JsonSchema;
3use crate::{gen::SchemaGenerator, Map};
4use serde_json::{Error, Value};
5use std::{convert::TryInto, fmt::Display};
6
7pub(crate) struct Serializer<'a> {
8    pub(crate) gen: &'a mut SchemaGenerator,
9    pub(crate) include_title: bool,
10}
11
12pub(crate) struct SerializeSeq<'a> {
13    gen: &'a mut SchemaGenerator,
14    items: Option<Schema>,
15}
16
17pub(crate) struct SerializeTuple<'a> {
18    gen: &'a mut SchemaGenerator,
19    items: Vec<Schema>,
20    title: &'static str,
21}
22
23pub(crate) struct SerializeMap<'a> {
24    gen: &'a mut SchemaGenerator,
25    properties: Map<String, Schema>,
26    current_key: Option<String>,
27    title: &'static str,
28}
29
30macro_rules! forward_to_subschema_for {
31    ($fn:ident, $ty:ty) => {
32        fn $fn(self, _value: $ty) -> Result<Self::Ok, Self::Error> {
33            Ok(self.gen.subschema_for::<$ty>())
34        }
35    };
36}
37
38macro_rules! return_instance_type {
39    ($fn:ident, $ty:ty, $instance_type:ident) => {
40        fn $fn(self, _value: $ty) -> Result<Self::Ok, Self::Error> {
41            Ok(SchemaObject {
42                instance_type: Some(InstanceType::$instance_type.into()),
43                ..Default::default()
44            }
45            .into())
46        }
47    };
48}
49
50impl<'a> serde::Serializer for Serializer<'a> {
51    type Ok = Schema;
52    type Error = Error;
53
54    type SerializeSeq = SerializeSeq<'a>;
55    type SerializeTuple = SerializeTuple<'a>;
56    type SerializeTupleStruct = SerializeTuple<'a>;
57    type SerializeTupleVariant = Self;
58    type SerializeMap = SerializeMap<'a>;
59    type SerializeStruct = SerializeMap<'a>;
60    type SerializeStructVariant = Self;
61
62    return_instance_type!(serialize_i8, i8, Integer);
63    return_instance_type!(serialize_i16, i16, Integer);
64    return_instance_type!(serialize_i32, i32, Integer);
65    return_instance_type!(serialize_i64, i64, Integer);
66    return_instance_type!(serialize_i128, i128, Integer);
67    return_instance_type!(serialize_u8, u8, Integer);
68    return_instance_type!(serialize_u16, u16, Integer);
69    return_instance_type!(serialize_u32, u32, Integer);
70    return_instance_type!(serialize_u64, u64, Integer);
71    return_instance_type!(serialize_u128, u128, Integer);
72    return_instance_type!(serialize_f32, f32, Number);
73    return_instance_type!(serialize_f64, f64, Number);
74
75    forward_to_subschema_for!(serialize_bool, bool);
76    forward_to_subschema_for!(serialize_char, char);
77    forward_to_subschema_for!(serialize_str, &str);
78    forward_to_subschema_for!(serialize_bytes, &[u8]);
79
80    fn collect_str<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
81    where
82        T: Display,
83    {
84        Ok(self.gen.subschema_for::<&str>())
85    }
86
87    fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
88    where
89        K: serde::Serialize,
90        V: serde::Serialize,
91        I: IntoIterator<Item = (K, V)>,
92    {
93        let value_schema = iter
94            .into_iter()
95            .try_fold(None, |acc, (_, v)| {
96                if acc == Some(Schema::Bool(true)) {
97                    return Ok(acc);
98                }
99
100                let schema = v.serialize(Serializer {
101                    gen: self.gen,
102                    include_title: false,
103                })?;
104                Ok(match &acc {
105                    None => Some(schema),
106                    Some(items) if items != &schema => Some(Schema::Bool(true)),
107                    _ => acc,
108                })
109            })?
110            .unwrap_or(Schema::Bool(true));
111
112        Ok(SchemaObject {
113            instance_type: Some(InstanceType::Object.into()),
114            object: Some(Box::new(ObjectValidation {
115                additional_properties: Some(Box::new(value_schema)),
116                ..ObjectValidation::default()
117            })),
118            ..SchemaObject::default()
119        }
120        .into())
121    }
122
123    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
124        Ok(self.gen.subschema_for::<Option<Value>>())
125    }
126
127    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
128        self.serialize_none()
129    }
130
131    fn serialize_some<T: ?Sized>(mut self, value: &T) -> Result<Self::Ok, Self::Error>
132    where
133        T: serde::Serialize,
134    {
135        // FIXME nasty duplication of `impl JsonSchema for Option<T>`
136        fn add_null_type(instance_type: &mut SingleOrVec<InstanceType>) {
137            match instance_type {
138                SingleOrVec::Single(ty) if **ty != InstanceType::Null => {
139                    *instance_type = vec![**ty, InstanceType::Null].into()
140                }
141                SingleOrVec::Vec(ty) if !ty.contains(&InstanceType::Null) => {
142                    ty.push(InstanceType::Null)
143                }
144                _ => {}
145            };
146        }
147
148        let mut schema = value.serialize(Serializer {
149            gen: self.gen,
150            include_title: false,
151        })?;
152
153        if self.gen.settings().option_add_null_type {
154            schema = match schema {
155                Schema::Bool(true) => Schema::Bool(true),
156                Schema::Bool(false) => <()>::json_schema(&mut self.gen),
157                Schema::Object(SchemaObject {
158                    instance_type: Some(ref mut instance_type),
159                    ..
160                }) => {
161                    add_null_type(instance_type);
162                    schema
163                }
164                schema => SchemaObject {
165                    subschemas: Some(Box::new(SubschemaValidation {
166                        any_of: Some(vec![schema, <()>::json_schema(&mut self.gen)]),
167                        ..Default::default()
168                    })),
169                    ..Default::default()
170                }
171                .into(),
172            }
173        }
174
175        if self.gen.settings().option_nullable {
176            let mut schema_obj = schema.into_object();
177            schema_obj
178                .extensions
179                .insert("nullable".to_owned(), serde_json::json!(true));
180            schema = Schema::Object(schema_obj);
181        };
182
183        Ok(schema)
184    }
185
186    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
187        Ok(self.gen.subschema_for::<()>())
188    }
189
190    fn serialize_unit_variant(
191        self,
192        _name: &'static str,
193        _variant_index: u32,
194        _variant: &'static str,
195    ) -> Result<Self::Ok, Self::Error> {
196        Ok(Schema::Bool(true))
197    }
198
199    fn serialize_newtype_struct<T: ?Sized>(
200        self,
201        name: &'static str,
202        value: &T,
203    ) -> Result<Self::Ok, Self::Error>
204    where
205        T: serde::Serialize,
206    {
207        let include_title = self.include_title;
208        let mut result = value.serialize(self);
209
210        if include_title {
211            if let Ok(Schema::Object(ref mut object)) = result {
212                object.metadata().title = Some(name.to_string());
213            }
214        }
215
216        result
217    }
218
219    fn serialize_newtype_variant<T: ?Sized>(
220        self,
221        _name: &'static str,
222        _variant_index: u32,
223        _variant: &'static str,
224        _value: &T,
225    ) -> Result<Self::Ok, Self::Error>
226    where
227        T: serde::Serialize,
228    {
229        Ok(Schema::Bool(true))
230    }
231
232    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
233        Ok(SerializeSeq {
234            gen: self.gen,
235            items: None,
236        })
237    }
238
239    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
240        Ok(SerializeTuple {
241            gen: self.gen,
242            items: Vec::with_capacity(len),
243            title: "",
244        })
245    }
246
247    fn serialize_tuple_struct(
248        self,
249        name: &'static str,
250        len: usize,
251    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
252        let title = if self.include_title { name } else { "" };
253        Ok(SerializeTuple {
254            gen: self.gen,
255            items: Vec::with_capacity(len),
256            title,
257        })
258    }
259
260    fn serialize_tuple_variant(
261        self,
262        _name: &'static str,
263        _variant_index: u32,
264        _variant: &'static str,
265        _len: usize,
266    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
267        Ok(self)
268    }
269
270    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
271        Ok(SerializeMap {
272            gen: self.gen,
273            properties: Map::new(),
274            current_key: None,
275            title: "",
276        })
277    }
278
279    fn serialize_struct(
280        self,
281        name: &'static str,
282        _len: usize,
283    ) -> Result<Self::SerializeStruct, Self::Error> {
284        let title = if self.include_title { name } else { "" };
285        Ok(SerializeMap {
286            gen: self.gen,
287            properties: Map::new(),
288            current_key: None,
289            title,
290        })
291    }
292
293    fn serialize_struct_variant(
294        self,
295        _name: &'static str,
296        _variant_index: u32,
297        _variant: &'static str,
298        _len: usize,
299    ) -> Result<Self::SerializeStructVariant, Self::Error> {
300        Ok(self)
301    }
302}
303
304impl serde::ser::SerializeTupleVariant for Serializer<'_> {
305    type Ok = Schema;
306    type Error = Error;
307
308    fn serialize_field<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error>
309    where
310        T: serde::Serialize,
311    {
312        Ok(())
313    }
314
315    fn end(self) -> Result<Self::Ok, Self::Error> {
316        Ok(Schema::Bool(true))
317    }
318}
319
320impl serde::ser::SerializeStructVariant for Serializer<'_> {
321    type Ok = Schema;
322    type Error = Error;
323
324    fn serialize_field<T: ?Sized>(
325        &mut self,
326        _key: &'static str,
327        _value: &T,
328    ) -> Result<(), Self::Error>
329    where
330        T: serde::Serialize,
331    {
332        Ok(())
333    }
334
335    fn end(self) -> Result<Self::Ok, Self::Error> {
336        Ok(Schema::Bool(true))
337    }
338}
339
340impl serde::ser::SerializeSeq for SerializeSeq<'_> {
341    type Ok = Schema;
342    type Error = Error;
343
344    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
345    where
346        T: serde::Serialize,
347    {
348        if self.items != Some(Schema::Bool(true)) {
349            let schema = value.serialize(Serializer {
350                gen: self.gen,
351                include_title: false,
352            })?;
353            match &self.items {
354                None => self.items = Some(schema),
355                Some(items) => {
356                    if items != &schema {
357                        self.items = Some(Schema::Bool(true))
358                    }
359                }
360            }
361        }
362
363        Ok(())
364    }
365
366    fn end(self) -> Result<Self::Ok, Self::Error> {
367        let items = self.items.unwrap_or(Schema::Bool(true));
368        Ok(SchemaObject {
369            instance_type: Some(InstanceType::Array.into()),
370            array: Some(Box::new(ArrayValidation {
371                items: Some(items.into()),
372                ..ArrayValidation::default()
373            })),
374            ..SchemaObject::default()
375        }
376        .into())
377    }
378}
379
380impl serde::ser::SerializeTuple for SerializeTuple<'_> {
381    type Ok = Schema;
382    type Error = Error;
383
384    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
385    where
386        T: serde::Serialize,
387    {
388        let schema = value.serialize(Serializer {
389            gen: self.gen,
390            include_title: false,
391        })?;
392        self.items.push(schema);
393        Ok(())
394    }
395
396    fn end(self) -> Result<Self::Ok, Self::Error> {
397        let len = self.items.len().try_into().ok();
398        let mut schema = SchemaObject {
399            instance_type: Some(InstanceType::Array.into()),
400            array: Some(Box::new(ArrayValidation {
401                items: Some(SingleOrVec::Vec(self.items)),
402                max_items: len,
403                min_items: len,
404                ..ArrayValidation::default()
405            })),
406            ..SchemaObject::default()
407        };
408
409        if !self.title.is_empty() {
410            schema.metadata().title = Some(self.title.to_owned());
411        }
412
413        Ok(schema.into())
414    }
415}
416
417impl serde::ser::SerializeTupleStruct for SerializeTuple<'_> {
418    type Ok = Schema;
419    type Error = Error;
420
421    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
422    where
423        T: serde::Serialize,
424    {
425        serde::ser::SerializeTuple::serialize_element(self, value)
426    }
427
428    fn end(self) -> Result<Self::Ok, Self::Error> {
429        serde::ser::SerializeTuple::end(self)
430    }
431}
432
433impl serde::ser::SerializeMap for SerializeMap<'_> {
434    type Ok = Schema;
435    type Error = Error;
436
437    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
438    where
439        T: serde::Serialize,
440    {
441        // FIXME this is too lenient - we should return an error if serde_json
442        // doesn't allow T to be a key of a map.
443        let json = serde_json::to_string(key)?;
444        self.current_key = Some(
445            json.trim_start_matches('"')
446                .trim_end_matches('"')
447                .to_string(),
448        );
449
450        Ok(())
451    }
452
453    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
454    where
455        T: serde::Serialize,
456    {
457        let key = self.current_key.take().unwrap_or_default();
458        let schema = value.serialize(Serializer {
459            gen: self.gen,
460            include_title: false,
461        })?;
462        self.properties.insert(key, schema);
463
464        Ok(())
465    }
466
467    fn end(self) -> Result<Self::Ok, Self::Error> {
468        let mut schema = SchemaObject {
469            instance_type: Some(InstanceType::Object.into()),
470            object: Some(Box::new(ObjectValidation {
471                properties: self.properties,
472                ..ObjectValidation::default()
473            })),
474            ..SchemaObject::default()
475        };
476
477        if !self.title.is_empty() {
478            schema.metadata().title = Some(self.title.to_owned());
479        }
480
481        Ok(schema.into())
482    }
483}
484
485impl serde::ser::SerializeStruct for SerializeMap<'_> {
486    type Ok = Schema;
487    type Error = Error;
488
489    fn serialize_field<T: ?Sized>(
490        &mut self,
491        key: &'static str,
492        value: &T,
493    ) -> Result<(), Self::Error>
494    where
495        T: serde::Serialize,
496    {
497        let prop_schema = value.serialize(Serializer {
498            gen: self.gen,
499            include_title: false,
500        })?;
501        self.properties.insert(key.to_string(), prop_schema);
502
503        Ok(())
504    }
505
506    fn end(self) -> Result<Self::Ok, Self::Error> {
507        serde::ser::SerializeMap::end(self)
508    }
509}