1use std::collections::BTreeMap;
6
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10use super::RefOr;
11use super::{builder, security::SecurityScheme, set_value, xml::Xml, Deprecated, Response};
12use crate::{ToResponse, ToSchema};
13
14macro_rules! component_from_builder {
15 ( $name:ident ) => {
16 impl From<$name> for Schema {
17 fn from(builder: $name) -> Self {
18 builder.build().into()
19 }
20 }
21 };
22}
23
24macro_rules! to_array_builder {
25 () => {
26 pub fn to_array_builder(self) -> ArrayBuilder {
28 ArrayBuilder::from(Array::new(self))
29 }
30 };
31}
32
33pub fn empty() -> Schema {
38 Schema::Object(
39 ObjectBuilder::new()
40 .schema_type(SchemaType::Value)
41 .nullable(true)
42 .default(Some(serde_json::Value::Null))
43 .into(),
44 )
45}
46
47builder! {
48 ComponentsBuilder;
49
50 #[non_exhaustive]
58 #[derive(Serialize, Deserialize, Default, Clone, PartialEq)]
59 #[cfg_attr(feature = "debug", derive(Debug))]
60 #[serde(rename_all = "camelCase")]
61 pub struct Components {
62 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
66 pub schemas: BTreeMap<String, RefOr<Schema>>,
67
68 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
74 pub responses: BTreeMap<String, RefOr<Response>>,
75
76 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
80 pub security_schemes: BTreeMap<String, SecurityScheme>,
81 }
82}
83
84impl Components {
85 pub fn new() -> Self {
87 Self {
88 ..Default::default()
89 }
90 }
91 pub fn add_security_scheme<N: Into<String>, S: Into<SecurityScheme>>(
98 &mut self,
99 name: N,
100 security_schema: S,
101 ) {
102 self.security_schemes
103 .insert(name.into(), security_schema.into());
104 }
105
106 pub fn add_security_schemes_from_iter<
113 I: IntoIterator<Item = (N, S)>,
114 N: Into<String>,
115 S: Into<SecurityScheme>,
116 >(
117 &mut self,
118 schemas: I,
119 ) {
120 self.security_schemes.extend(
121 schemas
122 .into_iter()
123 .map(|(name, item)| (name.into(), item.into())),
124 );
125 }
126}
127
128impl ComponentsBuilder {
129 pub fn schema<S: Into<String>, I: Into<RefOr<Schema>>>(mut self, name: S, schema: I) -> Self {
133 self.schemas.insert(name.into(), schema.into());
134
135 self
136 }
137
138 pub fn schema_from<'s, I: ToSchema<'s>>(mut self) -> Self {
139 let aliases = I::aliases();
140
141 if aliases.is_empty() {
146 let (name, schema) = I::schema();
147 self.schemas.insert(name.to_string(), schema);
148 }
149
150 self.schemas_from_iter(aliases)
151 }
152
153 pub fn schemas_from_iter<
172 I: IntoIterator<Item = (S, C)>,
173 C: Into<RefOr<Schema>>,
174 S: Into<String>,
175 >(
176 mut self,
177 schemas: I,
178 ) -> Self {
179 self.schemas.extend(
180 schemas
181 .into_iter()
182 .map(|(name, schema)| (name.into(), schema.into())),
183 );
184
185 self
186 }
187
188 pub fn response<S: Into<String>, R: Into<RefOr<Response>>>(
189 mut self,
190 name: S,
191 response: R,
192 ) -> Self {
193 self.responses.insert(name.into(), response.into());
194 self
195 }
196
197 pub fn response_from<'r, I: ToResponse<'r>>(self) -> Self {
198 let (name, response) = I::response();
199 self.response(name, response)
200 }
201
202 pub fn responses_from_iter<
203 I: IntoIterator<Item = (S, R)>,
204 S: Into<String>,
205 R: Into<RefOr<Response>>,
206 >(
207 mut self,
208 responses: I,
209 ) -> Self {
210 self.responses.extend(
211 responses
212 .into_iter()
213 .map(|(name, response)| (name.into(), response.into())),
214 );
215
216 self
217 }
218
219 pub fn security_scheme<N: Into<String>, S: Into<SecurityScheme>>(
226 mut self,
227 name: N,
228 security_schema: S,
229 ) -> Self {
230 self.security_schemes
231 .insert(name.into(), security_schema.into());
232
233 self
234 }
235}
236
237#[non_exhaustive]
242#[derive(Serialize, Deserialize, Clone, PartialEq)]
243#[cfg_attr(feature = "debug", derive(Debug))]
244#[serde(untagged, rename_all = "camelCase")]
245pub enum Schema {
246 Array(Array),
249 Object(Object),
252 OneOf(OneOf),
258
259 AllOf(AllOf),
263
264 AnyOf(AnyOf),
268}
269
270impl Default for Schema {
271 fn default() -> Self {
272 Schema::Object(Object::default())
273 }
274}
275
276#[derive(Serialize, Deserialize, Clone, Default, PartialEq, Eq)]
281#[serde(rename_all = "camelCase")]
282#[cfg_attr(feature = "debug", derive(Debug))]
283pub struct Discriminator {
284 pub property_name: String,
287}
288
289impl Discriminator {
290 pub fn new<I: Into<String>>(property_name: I) -> Self {
300 Self {
301 property_name: property_name.into(),
302 }
303 }
304}
305
306builder! {
307 OneOfBuilder;
308
309 #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
316 #[cfg_attr(feature = "debug", derive(Debug))]
317 pub struct OneOf {
318 #[serde(rename = "oneOf")]
320 pub items: Vec<RefOr<Schema>>,
321
322 #[serde(skip_serializing_if = "Option::is_none")]
324 pub title: Option<String>,
325
326 #[serde(skip_serializing_if = "Option::is_none")]
328 pub description: Option<String>,
329
330 #[serde(skip_serializing_if = "Option::is_none")]
332 pub default: Option<Value>,
333
334 #[serde(skip_serializing_if = "Option::is_none")]
336 pub example: Option<Value>,
337
338 #[serde(skip_serializing_if = "Option::is_none")]
341 pub discriminator: Option<Discriminator>,
342
343 #[serde(default, skip_serializing_if = "is_false")]
345 pub nullable: bool,
346 }
347}
348
349impl OneOf {
350 pub fn new() -> Self {
352 Self {
353 ..Default::default()
354 }
355 }
356
357 pub fn with_capacity(capacity: usize) -> Self {
370 Self {
371 items: Vec::with_capacity(capacity),
372 ..Default::default()
373 }
374 }
375}
376
377impl OneOfBuilder {
378 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
382 self.items.push(component.into());
383
384 self
385 }
386
387 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
389 set_value!(self title title.map(|title| title.into()))
390 }
391
392 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
394 set_value!(self description description.map(|description| description.into()))
395 }
396
397 pub fn default(mut self, default: Option<Value>) -> Self {
399 set_value!(self default default)
400 }
401
402 pub fn example(mut self, example: Option<Value>) -> Self {
404 set_value!(self example example)
405 }
406
407 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
409 set_value!(self discriminator discriminator)
410 }
411
412 pub fn nullable(mut self, nullable: bool) -> Self {
414 set_value!(self nullable nullable)
415 }
416
417 to_array_builder!();
418}
419
420impl From<OneOf> for Schema {
421 fn from(one_of: OneOf) -> Self {
422 Self::OneOf(one_of)
423 }
424}
425
426impl From<OneOfBuilder> for RefOr<Schema> {
427 fn from(one_of: OneOfBuilder) -> Self {
428 Self::T(Schema::OneOf(one_of.build()))
429 }
430}
431
432component_from_builder!(OneOfBuilder);
433
434builder! {
435 AllOfBuilder;
436
437 #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
444 #[cfg_attr(feature = "debug", derive(Debug))]
445 pub struct AllOf {
446 #[serde(rename = "allOf")]
448 pub items: Vec<RefOr<Schema>>,
449
450 #[serde(skip_serializing_if = "Option::is_none")]
452 pub title: Option<String>,
453
454 #[serde(skip_serializing_if = "Option::is_none")]
456 pub description: Option<String>,
457
458 #[serde(skip_serializing_if = "Option::is_none")]
460 pub default: Option<Value>,
461
462 #[serde(skip_serializing_if = "Option::is_none")]
464 pub example: Option<Value>,
465
466 #[serde(skip_serializing_if = "Option::is_none")]
469 pub discriminator: Option<Discriminator>,
470
471 #[serde(default, skip_serializing_if = "is_false")]
473 pub nullable: bool,
474 }
475}
476
477impl AllOf {
478 pub fn new() -> Self {
480 Self {
481 ..Default::default()
482 }
483 }
484
485 pub fn with_capacity(capacity: usize) -> Self {
498 Self {
499 items: Vec::with_capacity(capacity),
500 ..Default::default()
501 }
502 }
503}
504
505impl AllOfBuilder {
506 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
510 self.items.push(component.into());
511
512 self
513 }
514
515 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
517 set_value!(self title title.map(|title| title.into()))
518 }
519
520 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
522 set_value!(self description description.map(|description| description.into()))
523 }
524
525 pub fn default(mut self, default: Option<Value>) -> Self {
527 set_value!(self default default)
528 }
529
530 pub fn example(mut self, example: Option<Value>) -> Self {
532 set_value!(self example example)
533 }
534
535 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
537 set_value!(self discriminator discriminator)
538 }
539
540 pub fn nullable(mut self, nullable: bool) -> Self {
542 set_value!(self nullable nullable)
543 }
544
545 to_array_builder!();
546}
547
548impl From<AllOf> for Schema {
549 fn from(one_of: AllOf) -> Self {
550 Self::AllOf(one_of)
551 }
552}
553
554impl From<AllOfBuilder> for RefOr<Schema> {
555 fn from(one_of: AllOfBuilder) -> Self {
556 Self::T(Schema::AllOf(one_of.build()))
557 }
558}
559
560component_from_builder!(AllOfBuilder);
561
562builder! {
563 AnyOfBuilder;
564
565 #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
572 #[cfg_attr(feature = "debug", derive(Debug))]
573 pub struct AnyOf {
574 #[serde(rename = "anyOf")]
576 pub items: Vec<RefOr<Schema>>,
577
578 #[serde(skip_serializing_if = "Option::is_none")]
580 pub description: Option<String>,
581
582 #[serde(skip_serializing_if = "Option::is_none")]
584 pub default: Option<Value>,
585
586 #[serde(skip_serializing_if = "Option::is_none")]
588 pub example: Option<Value>,
589
590 #[serde(skip_serializing_if = "Option::is_none")]
593 pub discriminator: Option<Discriminator>,
594
595 #[serde(default, skip_serializing_if = "is_false")]
597 pub nullable: bool,
598 }
599}
600
601impl AnyOf {
602 pub fn new() -> Self {
604 Self {
605 ..Default::default()
606 }
607 }
608
609 pub fn with_capacity(capacity: usize) -> Self {
622 Self {
623 items: Vec::with_capacity(capacity),
624 ..Default::default()
625 }
626 }
627}
628
629impl AnyOfBuilder {
630 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
634 self.items.push(component.into());
635
636 self
637 }
638
639 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
641 set_value!(self description description.map(|description| description.into()))
642 }
643
644 pub fn default(mut self, default: Option<Value>) -> Self {
646 set_value!(self default default)
647 }
648
649 pub fn example(mut self, example: Option<Value>) -> Self {
651 set_value!(self example example)
652 }
653
654 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
656 set_value!(self discriminator discriminator)
657 }
658
659 pub fn nullable(mut self, nullable: bool) -> Self {
661 set_value!(self nullable nullable)
662 }
663
664 to_array_builder!();
665}
666
667impl From<AnyOf> for Schema {
668 fn from(any_of: AnyOf) -> Self {
669 Self::AnyOf(any_of)
670 }
671}
672
673impl From<AnyOfBuilder> for RefOr<Schema> {
674 fn from(any_of: AnyOfBuilder) -> Self {
675 Self::T(Schema::AnyOf(any_of.build()))
676 }
677}
678
679component_from_builder!(AnyOfBuilder);
680
681#[cfg(not(feature = "preserve_order"))]
682type ObjectPropertiesMap<K, V> = BTreeMap<K, V>;
683#[cfg(feature = "preserve_order")]
684type ObjectPropertiesMap<K, V> = indexmap::IndexMap<K, V>;
685
686builder! {
687 ObjectBuilder;
688
689 #[non_exhaustive]
696 #[derive(Serialize, Deserialize, Default, Clone, PartialEq)]
697 #[cfg_attr(feature = "debug", derive(Debug))]
698 #[serde(rename_all = "camelCase")]
699 pub struct Object {
700 #[serde(rename = "type", skip_serializing_if="SchemaType::is_value")]
703 pub schema_type: SchemaType,
704
705 #[serde(skip_serializing_if = "Option::is_none")]
707 pub title: Option<String>,
708
709 #[serde(skip_serializing_if = "Option::is_none")]
711 pub format: Option<SchemaFormat>,
712
713 #[serde(skip_serializing_if = "Option::is_none")]
715 pub description: Option<String>,
716
717 #[serde(skip_serializing_if = "Option::is_none")]
719 pub default: Option<Value>,
720
721 #[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
723 pub enum_values: Option<Vec<Value>>,
724
725 #[serde(skip_serializing_if = "Vec::is_empty", default = "Vec::new")]
727 pub required: Vec<String>,
728
729 #[serde(skip_serializing_if = "ObjectPropertiesMap::is_empty", default = "ObjectPropertiesMap::new")]
737 pub properties: ObjectPropertiesMap<String, RefOr<Schema>>,
738
739 #[serde(skip_serializing_if = "Option::is_none")]
741 pub additional_properties: Option<Box<AdditionalProperties<Schema>>>,
742
743 #[serde(skip_serializing_if = "Option::is_none")]
745 pub deprecated: Option<Deprecated>,
746
747 #[serde(skip_serializing_if = "Option::is_none")]
749 pub example: Option<Value>,
750
751 #[serde(skip_serializing_if = "Option::is_none")]
753 pub write_only: Option<bool>,
754
755 #[serde(skip_serializing_if = "Option::is_none")]
757 pub read_only: Option<bool>,
758
759 #[serde(skip_serializing_if = "Option::is_none")]
761 pub xml: Option<Xml>,
762
763 #[serde(default, skip_serializing_if = "is_false")]
765 pub nullable: bool,
766
767 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
770 pub multiple_of: Option<f64>,
771
772 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
775 pub maximum: Option<f64>,
776
777 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
780 pub minimum: Option<f64>,
781
782 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
785 pub exclusive_maximum: Option<f64>,
786
787 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
790 pub exclusive_minimum: Option<f64>,
791
792 #[serde(skip_serializing_if = "Option::is_none")]
795 pub max_length: Option<usize>,
796
797 #[serde(skip_serializing_if = "Option::is_none")]
801 pub min_length: Option<usize>,
802
803 #[serde(skip_serializing_if = "Option::is_none")]
806 pub pattern: Option<String>,
807
808 #[serde(skip_serializing_if = "Option::is_none")]
810 pub max_properties: Option<usize>,
811
812 #[serde(skip_serializing_if = "Option::is_none")]
815 pub min_properties: Option<usize>,
816 }
817}
818
819fn is_false(value: &bool) -> bool {
820 !*value
821}
822
823impl Object {
824 pub fn new() -> Self {
827 Self {
828 ..Default::default()
829 }
830 }
831
832 pub fn with_type(schema_type: SchemaType) -> Self {
840 Self {
841 schema_type,
842 ..Default::default()
843 }
844 }
845}
846
847impl From<Object> for Schema {
848 fn from(s: Object) -> Self {
849 Self::Object(s)
850 }
851}
852
853impl ToArray for Object {}
854
855impl ObjectBuilder {
856 pub fn schema_type(mut self, schema_type: SchemaType) -> Self {
858 set_value!(self schema_type schema_type)
859 }
860
861 pub fn format(mut self, format: Option<SchemaFormat>) -> Self {
863 set_value!(self format format)
864 }
865
866 pub fn property<S: Into<String>, I: Into<RefOr<Schema>>>(
870 mut self,
871 property_name: S,
872 component: I,
873 ) -> Self {
874 self.properties
875 .insert(property_name.into(), component.into());
876
877 self
878 }
879
880 pub fn additional_properties<I: Into<AdditionalProperties<Schema>>>(
881 mut self,
882 additional_properties: Option<I>,
883 ) -> Self {
884 set_value!(self additional_properties additional_properties.map(|additional_properties| Box::new(additional_properties.into())))
885 }
886
887 pub fn required<I: Into<String>>(mut self, required_field: I) -> Self {
889 self.required.push(required_field.into());
890
891 self
892 }
893
894 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
896 set_value!(self title title.map(|title| title.into()))
897 }
898
899 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
901 set_value!(self description description.map(|description| description.into()))
902 }
903
904 pub fn default(mut self, default: Option<Value>) -> Self {
906 set_value!(self default default)
907 }
908
909 pub fn deprecated(mut self, deprecated: Option<Deprecated>) -> Self {
911 set_value!(self deprecated deprecated)
912 }
913
914 pub fn enum_values<I: IntoIterator<Item = E>, E: Into<Value>>(
916 mut self,
917 enum_values: Option<I>,
918 ) -> Self {
919 set_value!(self enum_values
920 enum_values.map(|values| values.into_iter().map(|enum_value| enum_value.into()).collect()))
921 }
922
923 pub fn example(mut self, example: Option<Value>) -> Self {
925 set_value!(self example example)
926 }
927
928 pub fn write_only(mut self, write_only: Option<bool>) -> Self {
930 set_value!(self write_only write_only)
931 }
932
933 pub fn read_only(mut self, read_only: Option<bool>) -> Self {
935 set_value!(self read_only read_only)
936 }
937
938 pub fn xml(mut self, xml: Option<Xml>) -> Self {
940 set_value!(self xml xml)
941 }
942
943 pub fn nullable(mut self, nullable: bool) -> Self {
945 set_value!(self nullable nullable)
946 }
947
948 pub fn multiple_of(mut self, multiple_of: Option<f64>) -> Self {
950 set_value!(self multiple_of multiple_of)
951 }
952
953 pub fn maximum(mut self, maximum: Option<f64>) -> Self {
955 set_value!(self maximum maximum)
956 }
957
958 pub fn minimum(mut self, minimum: Option<f64>) -> Self {
960 set_value!(self minimum minimum)
961 }
962
963 pub fn exclusive_maximum(mut self, exclusive_maximum: Option<f64>) -> Self {
965 set_value!(self exclusive_maximum exclusive_maximum)
966 }
967
968 pub fn exclusive_minimum(mut self, exclusive_minimum: Option<f64>) -> Self {
970 set_value!(self exclusive_minimum exclusive_minimum)
971 }
972
973 pub fn max_length(mut self, max_length: Option<usize>) -> Self {
975 set_value!(self max_length max_length)
976 }
977
978 pub fn min_length(mut self, min_length: Option<usize>) -> Self {
980 set_value!(self min_length min_length)
981 }
982
983 pub fn pattern<I: Into<String>>(mut self, pattern: Option<I>) -> Self {
985 set_value!(self pattern pattern.map(|pattern| pattern.into()))
986 }
987
988 pub fn max_properties(mut self, max_properties: Option<usize>) -> Self {
990 set_value!(self max_properties max_properties)
991 }
992
993 pub fn min_properties(mut self, min_properties: Option<usize>) -> Self {
995 set_value!(self min_properties min_properties)
996 }
997
998 to_array_builder!();
999}
1000
1001component_from_builder!(ObjectBuilder);
1002
1003impl From<ObjectBuilder> for RefOr<Schema> {
1004 fn from(builder: ObjectBuilder) -> Self {
1005 Self::T(Schema::Object(builder.build()))
1006 }
1007}
1008
1009#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1013#[cfg_attr(feature = "debug", derive(Debug))]
1014#[serde(untagged)]
1015pub enum AdditionalProperties<T> {
1016 RefOr(RefOr<T>),
1018 FreeForm(bool),
1020}
1021
1022impl<T> From<RefOr<T>> for AdditionalProperties<T> {
1023 fn from(value: RefOr<T>) -> Self {
1024 Self::RefOr(value)
1025 }
1026}
1027
1028impl From<ObjectBuilder> for AdditionalProperties<Schema> {
1029 fn from(value: ObjectBuilder) -> Self {
1030 Self::RefOr(RefOr::T(Schema::Object(value.build())))
1031 }
1032}
1033
1034impl From<Ref> for AdditionalProperties<Schema> {
1035 fn from(value: Ref) -> Self {
1036 Self::RefOr(RefOr::Ref(value))
1037 }
1038}
1039
1040impl From<Schema> for AdditionalProperties<Schema> {
1041 fn from(value: Schema) -> Self {
1042 Self::RefOr(RefOr::T(value))
1043 }
1044}
1045
1046#[non_exhaustive]
1051#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq)]
1052#[cfg_attr(feature = "debug", derive(Debug))]
1053pub struct Ref {
1054 #[serde(rename = "$ref")]
1056 pub ref_location: String,
1057}
1058
1059impl Ref {
1060 pub fn new<I: Into<String>>(ref_location: I) -> Self {
1063 Self {
1064 ref_location: ref_location.into(),
1065 }
1066 }
1067
1068 pub fn from_schema_name<I: Into<String>>(schema_name: I) -> Self {
1071 Self::new(format!("#/components/schemas/{}", schema_name.into()))
1072 }
1073
1074 pub fn from_response_name<I: Into<String>>(response_name: I) -> Self {
1077 Self::new(format!("#/components/responses/{}", response_name.into()))
1078 }
1079
1080 to_array_builder!();
1081}
1082
1083impl From<Ref> for RefOr<Schema> {
1084 fn from(r: Ref) -> Self {
1085 Self::Ref(r)
1086 }
1087}
1088
1089impl<T> From<T> for RefOr<T> {
1090 fn from(t: T) -> Self {
1091 Self::T(t)
1092 }
1093}
1094
1095impl Default for RefOr<Schema> {
1096 fn default() -> Self {
1097 Self::T(Schema::Object(Object::new()))
1098 }
1099}
1100
1101impl ToArray for RefOr<Schema> {}
1102
1103impl From<Object> for RefOr<Schema> {
1104 fn from(object: Object) -> Self {
1105 Self::T(Schema::Object(object))
1106 }
1107}
1108
1109impl From<Array> for RefOr<Schema> {
1110 fn from(array: Array) -> Self {
1111 Self::T(Schema::Array(array))
1112 }
1113}
1114
1115fn omit_decimal_zero<S>(maybe_value: &Option<f64>, s: S) -> Result<S::Ok, S::Error>
1116where
1117 S: serde::Serializer,
1118{
1119 if let Some(v) = maybe_value {
1120 if v.fract() == 0.0 && *v >= i64::MIN as f64 && *v <= i64::MAX as f64 {
1121 s.serialize_i64(v.trunc() as i64)
1122 } else {
1123 s.serialize_f64(*v)
1124 }
1125 } else {
1126 s.serialize_none()
1127 }
1128}
1129
1130builder! {
1131 ArrayBuilder;
1132
1133 #[non_exhaustive]
1137 #[derive(Serialize, Deserialize, Clone, PartialEq)]
1138 #[cfg_attr(feature = "debug", derive(Debug))]
1139 #[serde(rename_all = "camelCase")]
1140 pub struct Array {
1141 #[serde(rename = "type")]
1143 pub schema_type: SchemaType,
1144
1145 #[serde(skip_serializing_if = "Option::is_none")]
1147 pub title: Option<String>,
1148
1149 pub items: Box<RefOr<Schema>>,
1151
1152 #[serde(skip_serializing_if = "Option::is_none")]
1154 pub description: Option<String>,
1155
1156 #[serde(skip_serializing_if = "Option::is_none")]
1158 pub deprecated: Option<Deprecated>,
1159
1160 #[serde(skip_serializing_if = "Option::is_none")]
1162 pub example: Option<Value>,
1163
1164 #[serde(skip_serializing_if = "Option::is_none")]
1166 pub default: Option<Value>,
1167
1168 #[serde(skip_serializing_if = "Option::is_none")]
1170 pub max_items: Option<usize>,
1171
1172 #[serde(skip_serializing_if = "Option::is_none")]
1174 pub min_items: Option<usize>,
1175
1176 #[serde(default, skip_serializing_if = "is_false")]
1179 pub unique_items: bool,
1180
1181 #[serde(skip_serializing_if = "Option::is_none")]
1183 pub xml: Option<Xml>,
1184
1185 #[serde(default, skip_serializing_if = "is_false")]
1187 pub nullable: bool,
1188 }
1189}
1190
1191impl Default for Array {
1192 fn default() -> Self {
1193 Self {
1194 title: Default::default(),
1195 schema_type: SchemaType::Array,
1196 unique_items: bool::default(),
1197 items: Default::default(),
1198 description: Default::default(),
1199 deprecated: Default::default(),
1200 example: Default::default(),
1201 default: Default::default(),
1202 max_items: Default::default(),
1203 min_items: Default::default(),
1204 xml: Default::default(),
1205 nullable: Default::default(),
1206 }
1207 }
1208}
1209
1210impl Array {
1211 pub fn new<I: Into<RefOr<Schema>>>(component: I) -> Self {
1221 Self {
1222 items: Box::new(component.into()),
1223 ..Default::default()
1224 }
1225 }
1226}
1227
1228impl ArrayBuilder {
1229 pub fn items<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
1231 set_value!(self items Box::new(component.into()))
1232 }
1233
1234 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
1236 set_value!(self title title.map(|title| title.into()))
1237 }
1238
1239 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
1241 set_value!(self description description.map(|description| description.into()))
1242 }
1243
1244 pub fn deprecated(mut self, deprecated: Option<Deprecated>) -> Self {
1246 set_value!(self deprecated deprecated)
1247 }
1248
1249 pub fn example(mut self, example: Option<Value>) -> Self {
1251 set_value!(self example example)
1252 }
1253
1254 pub fn default(mut self, default: Option<Value>) -> Self {
1256 set_value!(self default default)
1257 }
1258
1259 pub fn max_items(mut self, max_items: Option<usize>) -> Self {
1261 set_value!(self max_items max_items)
1262 }
1263
1264 pub fn min_items(mut self, min_items: Option<usize>) -> Self {
1266 set_value!(self min_items min_items)
1267 }
1268
1269 pub fn unique_items(mut self, unique_items: bool) -> Self {
1271 set_value!(self unique_items unique_items)
1272 }
1273
1274 pub fn xml(mut self, xml: Option<Xml>) -> Self {
1276 set_value!(self xml xml)
1277 }
1278
1279 pub fn nullable(mut self, nullable: bool) -> Self {
1281 set_value!(self nullable nullable)
1282 }
1283
1284 to_array_builder!();
1285}
1286
1287component_from_builder!(ArrayBuilder);
1288
1289impl From<Array> for Schema {
1290 fn from(array: Array) -> Self {
1291 Self::Array(array)
1292 }
1293}
1294
1295impl From<ArrayBuilder> for RefOr<Schema> {
1296 fn from(array: ArrayBuilder) -> Self {
1297 Self::T(Schema::Array(array.build()))
1298 }
1299}
1300
1301impl ToArray for Array {}
1302
1303pub trait ToArray
1304where
1305 RefOr<Schema>: From<Self>,
1306 Self: Sized,
1307{
1308 fn to_array(self) -> Array {
1309 Array::new(self)
1310 }
1311}
1312
1313#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1315#[cfg_attr(feature = "debug", derive(Debug))]
1316#[serde(rename_all = "lowercase")]
1317pub enum SchemaType {
1318 Object,
1321 Value,
1324 String,
1327 Integer,
1330 Number,
1333 Boolean,
1336 Array,
1338}
1339impl SchemaType {
1340 fn is_value(type_: &SchemaType) -> bool {
1341 *type_ == SchemaType::Value
1342 }
1343}
1344
1345impl Default for SchemaType {
1346 fn default() -> Self {
1347 Self::Object
1348 }
1349}
1350
1351#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1356#[cfg_attr(feature = "debug", derive(Debug))]
1357#[serde(rename_all = "lowercase", untagged)]
1358pub enum SchemaFormat {
1359 KnownFormat(KnownFormat),
1361 Custom(String),
1364}
1365
1366#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1368#[cfg_attr(feature = "debug", derive(Debug))]
1369#[serde(rename_all = "lowercase")]
1370pub enum KnownFormat {
1371 #[cfg(feature = "non_strict_integers")]
1373 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
1374 Int8,
1375 #[cfg(feature = "non_strict_integers")]
1377 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
1378 Int16,
1379 Int32,
1381 Int64,
1383 #[cfg(feature = "non_strict_integers")]
1385 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
1386 UInt8,
1387 #[cfg(feature = "non_strict_integers")]
1389 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
1390 UInt16,
1391 #[cfg(feature = "non_strict_integers")]
1393 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
1394 UInt32,
1395 #[cfg(feature = "non_strict_integers")]
1397 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
1398 UInt64,
1399 Float,
1401 Double,
1403 Byte,
1405 Binary,
1407 Date,
1409 #[serde(rename = "date-time")]
1411 DateTime,
1412 Password,
1414 #[cfg(feature = "uuid")]
1418 #[cfg_attr(doc_cfg, doc(cfg(feature = "uuid")))]
1419 Uuid,
1420 #[cfg(feature = "ulid")]
1424 #[cfg_attr(doc_cfg, doc(cfg(feature = "ulid")))]
1425 Ulid,
1426}
1427
1428#[cfg(test)]
1429mod tests {
1430 use assert_json_diff::assert_json_eq;
1431 use serde_json::{json, Value};
1432
1433 use super::*;
1434 use crate::openapi::*;
1435
1436 #[test]
1437 fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
1438 let openapi = OpenApiBuilder::new()
1439 .info(Info::new("My api", "1.0.0"))
1440 .paths(Paths::new())
1441 .components(Some(
1442 ComponentsBuilder::new()
1443 .schema("Person", Ref::new("#/components/PersonModel"))
1444 .schema(
1445 "Credential",
1446 Schema::from(
1447 ObjectBuilder::new()
1448 .property(
1449 "id",
1450 ObjectBuilder::new()
1451 .schema_type(SchemaType::Integer)
1452 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
1453 .description(Some("Id of credential"))
1454 .default(Some(json!(1i32))),
1455 )
1456 .property(
1457 "name",
1458 ObjectBuilder::new()
1459 .schema_type(SchemaType::String)
1460 .description(Some("Name of credential")),
1461 )
1462 .property(
1463 "status",
1464 ObjectBuilder::new()
1465 .schema_type(SchemaType::String)
1466 .default(Some(json!("Active")))
1467 .description(Some("Credential status"))
1468 .enum_values(Some([
1469 "Active",
1470 "NotActive",
1471 "Locked",
1472 "Expired",
1473 ])),
1474 )
1475 .property(
1476 "history",
1477 Array::new(Ref::from_schema_name("UpdateHistory")),
1478 )
1479 .property("tags", Object::with_type(SchemaType::String).to_array()),
1480 ),
1481 )
1482 .build(),
1483 ))
1484 .build();
1485
1486 let serialized = serde_json::to_string_pretty(&openapi)?;
1487 println!("serialized json:\n {serialized}");
1488
1489 let value = serde_json::to_value(&openapi)?;
1490 let credential = get_json_path(&value, "components.schemas.Credential.properties");
1491 let person = get_json_path(&value, "components.schemas.Person");
1492
1493 assert!(
1494 credential.get("id").is_some(),
1495 "could not find path: components.schemas.Credential.properties.id"
1496 );
1497 assert!(
1498 credential.get("status").is_some(),
1499 "could not find path: components.schemas.Credential.properties.status"
1500 );
1501 assert!(
1502 credential.get("name").is_some(),
1503 "could not find path: components.schemas.Credential.properties.name"
1504 );
1505 assert!(
1506 credential.get("history").is_some(),
1507 "could not find path: components.schemas.Credential.properties.history"
1508 );
1509 assert_eq!(
1510 credential
1511 .get("id")
1512 .unwrap_or(&serde_json::value::Value::Null)
1513 .to_string(),
1514 r#"{"default":1,"description":"Id of credential","format":"int32","type":"integer"}"#,
1515 "components.schemas.Credential.properties.id did not match"
1516 );
1517 assert_eq!(
1518 credential
1519 .get("name")
1520 .unwrap_or(&serde_json::value::Value::Null)
1521 .to_string(),
1522 r#"{"description":"Name of credential","type":"string"}"#,
1523 "components.schemas.Credential.properties.name did not match"
1524 );
1525 assert_eq!(
1526 credential
1527 .get("status")
1528 .unwrap_or(&serde_json::value::Value::Null)
1529 .to_string(),
1530 r#"{"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"}"#,
1531 "components.schemas.Credential.properties.status did not match"
1532 );
1533 assert_eq!(
1534 credential
1535 .get("history")
1536 .unwrap_or(&serde_json::value::Value::Null)
1537 .to_string(),
1538 r###"{"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"}"###,
1539 "components.schemas.Credential.properties.history did not match"
1540 );
1541 assert_eq!(
1542 person.to_string(),
1543 r###"{"$ref":"#/components/PersonModel"}"###,
1544 "components.schemas.Person.ref did not match"
1545 );
1546
1547 Ok(())
1548 }
1549
1550 #[test]
1552 fn test_property_order() {
1553 let json_value = ObjectBuilder::new()
1554 .property(
1555 "id",
1556 ObjectBuilder::new()
1557 .schema_type(SchemaType::Integer)
1558 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
1559 .description(Some("Id of credential"))
1560 .default(Some(json!(1i32))),
1561 )
1562 .property(
1563 "name",
1564 ObjectBuilder::new()
1565 .schema_type(SchemaType::String)
1566 .description(Some("Name of credential")),
1567 )
1568 .property(
1569 "status",
1570 ObjectBuilder::new()
1571 .schema_type(SchemaType::String)
1572 .default(Some(json!("Active")))
1573 .description(Some("Credential status"))
1574 .enum_values(Some(["Active", "NotActive", "Locked", "Expired"])),
1575 )
1576 .property(
1577 "history",
1578 Array::new(Ref::from_schema_name("UpdateHistory")),
1579 )
1580 .property("tags", Object::with_type(SchemaType::String).to_array())
1581 .build();
1582
1583 #[cfg(not(feature = "preserve_order"))]
1584 assert_eq!(
1585 json_value.properties.keys().collect::<Vec<_>>(),
1586 vec!["history", "id", "name", "status", "tags"]
1587 );
1588
1589 #[cfg(feature = "preserve_order")]
1590 assert_eq!(
1591 json_value.properties.keys().collect::<Vec<_>>(),
1592 vec!["id", "name", "status", "history", "tags"]
1593 );
1594 }
1595
1596 #[test]
1598 fn test_additional_properties() {
1599 let json_value = ObjectBuilder::new()
1600 .additional_properties(Some(ObjectBuilder::new().schema_type(SchemaType::String)))
1601 .build();
1602 assert_json_eq!(
1603 json_value,
1604 json!({
1605 "type": "object",
1606 "additionalProperties": {
1607 "type": "string"
1608 }
1609 })
1610 );
1611
1612 let json_value = ObjectBuilder::new()
1613 .additional_properties(Some(Ref::from_schema_name("ComplexModel")))
1614 .build();
1615 assert_json_eq!(
1616 json_value,
1617 json!({
1618 "type": "object",
1619 "additionalProperties": {
1620 "$ref": "#/components/schemas/ComplexModel"
1621 }
1622 })
1623 )
1624 }
1625
1626 #[test]
1627 fn test_object_with_title() {
1628 let json_value = ObjectBuilder::new().title(Some("SomeName")).build();
1629 assert_json_eq!(
1630 json_value,
1631 json!({
1632 "type": "object",
1633 "title": "SomeName"
1634 })
1635 );
1636 }
1637
1638 #[test]
1639 fn derive_object_with_example() {
1640 let expected = r#"{"type":"object","example":{"age":20,"name":"bob the cat"}}"#;
1641 let json_value = ObjectBuilder::new()
1642 .example(Some(json!({"age": 20, "name": "bob the cat"})))
1643 .build();
1644
1645 let value_string = serde_json::to_string(&json_value).unwrap();
1646 assert_eq!(
1647 value_string, expected,
1648 "value string != expected string, {value_string} != {expected}"
1649 );
1650 }
1651
1652 fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
1653 path.split('.').fold(value, |acc, fragment| {
1654 acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
1655 })
1656 }
1657
1658 #[test]
1659 fn test_array_new() {
1660 let array = Array::new(
1661 ObjectBuilder::new().property(
1662 "id",
1663 ObjectBuilder::new()
1664 .schema_type(SchemaType::Integer)
1665 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
1666 .description(Some("Id of credential"))
1667 .default(Some(json!(1i32))),
1668 ),
1669 );
1670
1671 assert!(matches!(array.schema_type, SchemaType::Array));
1672 }
1673
1674 #[test]
1675 fn test_array_builder() {
1676 let array: Array = ArrayBuilder::new()
1677 .items(
1678 ObjectBuilder::new().property(
1679 "id",
1680 ObjectBuilder::new()
1681 .schema_type(SchemaType::Integer)
1682 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
1683 .description(Some("Id of credential"))
1684 .default(Some(json!(1i32))),
1685 ),
1686 )
1687 .build();
1688
1689 assert!(matches!(array.schema_type, SchemaType::Array));
1690 }
1691
1692 #[test]
1693 fn reserialize_deserialized_schema_components() {
1694 let components = ComponentsBuilder::new()
1695 .schemas_from_iter(vec![(
1696 "Comp",
1697 Schema::from(
1698 ObjectBuilder::new()
1699 .property("name", ObjectBuilder::new().schema_type(SchemaType::String))
1700 .required("name"),
1701 ),
1702 )])
1703 .responses_from_iter(vec![(
1704 "200",
1705 ResponseBuilder::new().description("Okay").build(),
1706 )])
1707 .security_scheme("TLS", SecurityScheme::MutualTls { description: None })
1708 .build();
1709
1710 let serialized_components = serde_json::to_string(&components).unwrap();
1711
1712 let deserialized_components: Components =
1713 serde_json::from_str(serialized_components.as_str()).unwrap();
1714
1715 assert_eq!(
1716 serialized_components,
1717 serde_json::to_string(&deserialized_components).unwrap()
1718 )
1719 }
1720
1721 #[test]
1722 fn reserialize_deserialized_object_component() {
1723 let prop = ObjectBuilder::new()
1724 .property("name", ObjectBuilder::new().schema_type(SchemaType::String))
1725 .required("name")
1726 .build();
1727
1728 let serialized_components = serde_json::to_string(&prop).unwrap();
1729 let deserialized_components: Object =
1730 serde_json::from_str(serialized_components.as_str()).unwrap();
1731
1732 assert_eq!(
1733 serialized_components,
1734 serde_json::to_string(&deserialized_components).unwrap()
1735 )
1736 }
1737
1738 #[test]
1739 fn reserialize_deserialized_property() {
1740 let prop = ObjectBuilder::new().schema_type(SchemaType::String).build();
1741
1742 let serialized_components = serde_json::to_string(&prop).unwrap();
1743 let deserialized_components: Object =
1744 serde_json::from_str(serialized_components.as_str()).unwrap();
1745
1746 assert_eq!(
1747 serialized_components,
1748 serde_json::to_string(&deserialized_components).unwrap()
1749 )
1750 }
1751
1752 #[test]
1753 fn serialize_deserialize_array_within_ref_or_t_object_builder() {
1754 let ref_or_schema = RefOr::T(Schema::Object(
1755 ObjectBuilder::new()
1756 .property(
1757 "test",
1758 RefOr::T(Schema::Array(
1759 ArrayBuilder::new()
1760 .items(RefOr::T(Schema::Object(
1761 ObjectBuilder::new()
1762 .property("element", RefOr::Ref(Ref::new("#/test")))
1763 .build(),
1764 )))
1765 .build(),
1766 )),
1767 )
1768 .build(),
1769 ));
1770
1771 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1772 println!("----------------------------");
1773 println!("{json_str}");
1774
1775 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1776
1777 let json_de_str = serde_json::to_string(&deserialized).expect("");
1778 println!("----------------------------");
1779 println!("{json_de_str}");
1780
1781 assert_eq!(json_str, json_de_str);
1782 }
1783
1784 #[test]
1785 fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
1786 let ref_or_schema = RefOr::T(Schema::Object(
1787 ObjectBuilder::new()
1788 .property(
1789 "test",
1790 RefOr::T(Schema::OneOf(
1791 OneOfBuilder::new()
1792 .item(Schema::Array(
1793 ArrayBuilder::new()
1794 .items(RefOr::T(Schema::Object(
1795 ObjectBuilder::new()
1796 .property("element", RefOr::Ref(Ref::new("#/test")))
1797 .build(),
1798 )))
1799 .build(),
1800 ))
1801 .item(Schema::Array(
1802 ArrayBuilder::new()
1803 .items(RefOr::T(Schema::Object(
1804 ObjectBuilder::new()
1805 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
1806 .build(),
1807 )))
1808 .build(),
1809 ))
1810 .build(),
1811 )),
1812 )
1813 .build(),
1814 ));
1815
1816 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1817 println!("----------------------------");
1818 println!("{json_str}");
1819
1820 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1821
1822 let json_de_str = serde_json::to_string(&deserialized).expect("");
1823 println!("----------------------------");
1824 println!("{json_de_str}");
1825
1826 assert_eq!(json_str, json_de_str);
1827 }
1828
1829 #[test]
1830 fn serialize_deserialize_all_of_of_within_ref_or_t_object_builder() {
1831 let ref_or_schema = RefOr::T(Schema::Object(
1832 ObjectBuilder::new()
1833 .property(
1834 "test",
1835 RefOr::T(Schema::AllOf(
1836 AllOfBuilder::new()
1837 .item(Schema::Array(
1838 ArrayBuilder::new()
1839 .items(RefOr::T(Schema::Object(
1840 ObjectBuilder::new()
1841 .property("element", RefOr::Ref(Ref::new("#/test")))
1842 .build(),
1843 )))
1844 .build(),
1845 ))
1846 .item(RefOr::T(Schema::Object(
1847 ObjectBuilder::new()
1848 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
1849 .build(),
1850 )))
1851 .build(),
1852 )),
1853 )
1854 .build(),
1855 ));
1856
1857 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1858 println!("----------------------------");
1859 println!("{json_str}");
1860
1861 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1862
1863 let json_de_str = serde_json::to_string(&deserialized).expect("");
1864 println!("----------------------------");
1865 println!("{json_de_str}");
1866
1867 assert_eq!(json_str, json_de_str);
1868 }
1869
1870 #[test]
1871 fn serialize_deserialize_any_of_of_within_ref_or_t_object_builder() {
1872 let ref_or_schema = RefOr::T(Schema::Object(
1873 ObjectBuilder::new()
1874 .property(
1875 "test",
1876 RefOr::T(Schema::AnyOf(
1877 AnyOfBuilder::new()
1878 .item(Schema::Array(
1879 ArrayBuilder::new()
1880 .items(RefOr::T(Schema::Object(
1881 ObjectBuilder::new()
1882 .property("element", RefOr::Ref(Ref::new("#/test")))
1883 .build(),
1884 )))
1885 .build(),
1886 ))
1887 .item(RefOr::T(Schema::Object(
1888 ObjectBuilder::new()
1889 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
1890 .build(),
1891 )))
1892 .build(),
1893 )),
1894 )
1895 .build(),
1896 ));
1897
1898 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1899 println!("----------------------------");
1900 println!("{json_str}");
1901
1902 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1903
1904 let json_de_str = serde_json::to_string(&deserialized).expect("");
1905 println!("----------------------------");
1906 println!("{json_de_str}");
1907 assert!(json_str.contains("\"anyOf\""));
1908 assert_eq!(json_str, json_de_str);
1909 }
1910
1911 #[test]
1912 fn serialize_deserialize_schema_array_ref_or_t() {
1913 let ref_or_schema = RefOr::T(Schema::Array(
1914 ArrayBuilder::new()
1915 .items(RefOr::T(Schema::Object(
1916 ObjectBuilder::new()
1917 .property("element", RefOr::Ref(Ref::new("#/test")))
1918 .build(),
1919 )))
1920 .build(),
1921 ));
1922
1923 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1924 println!("----------------------------");
1925 println!("{json_str}");
1926
1927 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1928
1929 let json_de_str = serde_json::to_string(&deserialized).expect("");
1930 println!("----------------------------");
1931 println!("{json_de_str}");
1932
1933 assert_eq!(json_str, json_de_str);
1934 }
1935
1936 #[test]
1937 fn serialize_deserialize_schema_array_builder() {
1938 let ref_or_schema = ArrayBuilder::new()
1939 .items(RefOr::T(Schema::Object(
1940 ObjectBuilder::new()
1941 .property("element", RefOr::Ref(Ref::new("#/test")))
1942 .build(),
1943 )))
1944 .build();
1945
1946 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1947 println!("----------------------------");
1948 println!("{json_str}");
1949
1950 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1951
1952 let json_de_str = serde_json::to_string(&deserialized).expect("");
1953 println!("----------------------------");
1954 println!("{json_de_str}");
1955
1956 assert_eq!(json_str, json_de_str);
1957 }
1958
1959 #[test]
1960 fn serialize_deserialize_schema_with_additional_properties() {
1961 let schema = Schema::Object(
1962 ObjectBuilder::new()
1963 .property(
1964 "map",
1965 ObjectBuilder::new()
1966 .additional_properties(Some(AdditionalProperties::FreeForm(true))),
1967 )
1968 .build(),
1969 );
1970
1971 let json_str = serde_json::to_string(&schema).unwrap();
1972 println!("----------------------------");
1973 println!("{json_str}");
1974
1975 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
1976
1977 let json_de_str = serde_json::to_string(&deserialized).unwrap();
1978 println!("----------------------------");
1979 println!("{json_de_str}");
1980
1981 assert_eq!(json_str, json_de_str);
1982 }
1983
1984 #[test]
1985 fn serialize_deserialize_schema_with_additional_properties_object() {
1986 let schema = Schema::Object(
1987 ObjectBuilder::new()
1988 .property(
1989 "map",
1990 ObjectBuilder::new().additional_properties(Some(
1991 ObjectBuilder::new()
1992 .property("name", Object::with_type(SchemaType::String)),
1993 )),
1994 )
1995 .build(),
1996 );
1997
1998 let json_str = serde_json::to_string(&schema).unwrap();
1999 println!("----------------------------");
2000 println!("{json_str}");
2001
2002 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
2003
2004 let json_de_str = serde_json::to_string(&deserialized).unwrap();
2005 println!("----------------------------");
2006 println!("{json_de_str}");
2007
2008 assert_eq!(json_str, json_de_str);
2009 }
2010}