1use std::collections::BTreeMap;
6
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10use super::extensions::Extensions;
11use super::RefOr;
12use super::{builder, security::SecurityScheme, set_value, xml::Xml, Deprecated, Response};
13use crate::{ToResponse, ToSchema};
14
15macro_rules! component_from_builder {
16 ( $name:ident ) => {
17 impl From<$name> for Schema {
18 fn from(builder: $name) -> Self {
19 builder.build().into()
20 }
21 }
22 };
23}
24
25macro_rules! to_array_builder {
26 () => {
27 pub fn to_array_builder(self) -> ArrayBuilder {
29 ArrayBuilder::from(Array::new(self))
30 }
31 };
32}
33
34pub fn empty() -> Schema {
39 Schema::Object(
40 ObjectBuilder::new()
41 .schema_type(SchemaType::AnyValue)
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 #[serde(skip_serializing_if = "Option::is_none", flatten)]
84 pub extensions: Option<Extensions>,
85 }
86}
87
88impl Components {
89 pub fn new() -> Self {
91 Self {
92 ..Default::default()
93 }
94 }
95 pub fn add_security_scheme<N: Into<String>, S: Into<SecurityScheme>>(
102 &mut self,
103 name: N,
104 security_scheme: S,
105 ) {
106 self.security_schemes
107 .insert(name.into(), security_scheme.into());
108 }
109
110 pub fn add_security_schemes_from_iter<
117 I: IntoIterator<Item = (N, S)>,
118 N: Into<String>,
119 S: Into<SecurityScheme>,
120 >(
121 &mut self,
122 schemas: I,
123 ) {
124 self.security_schemes.extend(
125 schemas
126 .into_iter()
127 .map(|(name, item)| (name.into(), item.into())),
128 );
129 }
130}
131
132impl ComponentsBuilder {
133 pub fn schema<S: Into<String>, I: Into<RefOr<Schema>>>(mut self, name: S, schema: I) -> Self {
137 self.schemas.insert(name.into(), schema.into());
138
139 self
140 }
141
142 pub fn schema_from<I: ToSchema>(mut self) -> Self {
159 let name = I::name();
160 let schema = I::schema();
161 self.schemas.insert(name.to_string(), schema);
162
163 self
164 }
165
166 pub fn schemas_from_iter<
185 I: IntoIterator<Item = (S, C)>,
186 C: Into<RefOr<Schema>>,
187 S: Into<String>,
188 >(
189 mut self,
190 schemas: I,
191 ) -> Self {
192 self.schemas.extend(
193 schemas
194 .into_iter()
195 .map(|(name, schema)| (name.into(), schema.into())),
196 );
197
198 self
199 }
200
201 pub fn response<S: Into<String>, R: Into<RefOr<Response>>>(
206 mut self,
207 name: S,
208 response: R,
209 ) -> Self {
210 self.responses.insert(name.into(), response.into());
211 self
212 }
213
214 pub fn response_from<'r, I: ToResponse<'r>>(self) -> Self {
220 let (name, response) = I::response();
221 self.response(name, response)
222 }
223
224 pub fn responses_from_iter<
229 I: IntoIterator<Item = (S, R)>,
230 S: Into<String>,
231 R: Into<RefOr<Response>>,
232 >(
233 mut self,
234 responses: I,
235 ) -> Self {
236 self.responses.extend(
237 responses
238 .into_iter()
239 .map(|(name, response)| (name.into(), response.into())),
240 );
241
242 self
243 }
244
245 pub fn security_scheme<N: Into<String>, S: Into<SecurityScheme>>(
252 mut self,
253 name: N,
254 security_scheme: S,
255 ) -> Self {
256 self.security_schemes
257 .insert(name.into(), security_scheme.into());
258
259 self
260 }
261
262 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
264 set_value!(self extensions extensions)
265 }
266}
267
268#[non_exhaustive]
273#[derive(Serialize, Deserialize, Clone, PartialEq)]
274#[cfg_attr(feature = "debug", derive(Debug))]
275#[serde(untagged, rename_all = "camelCase")]
276pub enum Schema {
277 Array(Array),
280 Object(Object),
283 OneOf(OneOf),
289
290 AllOf(AllOf),
294
295 AnyOf(AnyOf),
299}
300
301impl Default for Schema {
302 fn default() -> Self {
303 Schema::Object(Object::default())
304 }
305}
306
307#[derive(Serialize, Deserialize, Clone, Default, PartialEq, Eq)]
312#[serde(rename_all = "camelCase")]
313#[cfg_attr(feature = "debug", derive(Debug))]
314pub struct Discriminator {
315 pub property_name: String,
318
319 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
323 pub mapping: BTreeMap<String, String>,
324
325 #[serde(skip_serializing_if = "Option::is_none", flatten)]
327 pub extensions: Option<Extensions>,
328}
329
330impl Discriminator {
331 pub fn new<I: Into<String>>(property_name: I) -> Self {
341 Self {
342 property_name: property_name.into(),
343 mapping: BTreeMap::new(),
344 ..Default::default()
345 }
346 }
347
348 pub fn with_mapping<
365 P: Into<String>,
366 M: IntoIterator<Item = (K, V)>,
367 K: Into<String>,
368 V: Into<String>,
369 >(
370 property_name: P,
371 mapping: M,
372 ) -> Self {
373 Self {
374 property_name: property_name.into(),
375 mapping: BTreeMap::from_iter(
376 mapping
377 .into_iter()
378 .map(|(key, val)| (key.into(), val.into())),
379 ),
380 ..Default::default()
381 }
382 }
383}
384
385builder! {
386 OneOfBuilder;
387
388 #[derive(Serialize, Deserialize, Clone, PartialEq)]
395 #[cfg_attr(feature = "debug", derive(Debug))]
396 pub struct OneOf {
397 #[serde(rename = "oneOf")]
399 pub items: Vec<RefOr<Schema>>,
400
401 #[serde(rename = "type", default = "SchemaType::any", skip_serializing_if = "SchemaType::is_any_value")]
406 pub schema_type: SchemaType,
407
408 #[serde(skip_serializing_if = "Option::is_none")]
410 pub title: Option<String>,
411
412 #[serde(skip_serializing_if = "Option::is_none")]
414 pub description: Option<String>,
415
416 #[serde(skip_serializing_if = "Option::is_none")]
418 pub default: Option<Value>,
419
420 #[serde(skip_serializing_if = "Option::is_none")]
424 pub example: Option<Value>,
425
426 #[serde(skip_serializing_if = "Vec::is_empty", default)]
428 pub examples: Vec<Value>,
429
430 #[serde(skip_serializing_if = "Option::is_none")]
433 pub discriminator: Option<Discriminator>,
434
435 #[serde(skip_serializing_if = "Option::is_none", flatten)]
437 pub extensions: Option<Extensions>,
438
439 #[serde(rename = "readOnly", skip_serializing_if = "Option::is_none")]
441 pub read_only: Option<bool>,
442
443 #[serde(rename = "writeOnly", skip_serializing_if = "Option::is_none")]
445 pub write_only: Option<bool>,
446 }
447}
448
449impl OneOf {
450 pub fn new() -> Self {
452 Self {
453 ..Default::default()
454 }
455 }
456
457 pub fn with_capacity(capacity: usize) -> Self {
470 Self {
471 items: Vec::with_capacity(capacity),
472 ..Default::default()
473 }
474 }
475}
476
477impl Default for OneOf {
478 fn default() -> Self {
479 Self {
480 items: Default::default(),
481 schema_type: SchemaType::AnyValue,
482 title: Default::default(),
483 description: Default::default(),
484 default: Default::default(),
485 example: Default::default(),
486 examples: Default::default(),
487 discriminator: Default::default(),
488 extensions: Default::default(),
489 read_only: Default::default(),
490 write_only: Default::default(),
491 }
492 }
493}
494
495impl OneOfBuilder {
496 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
500 self.items.push(component.into());
501
502 self
503 }
504
505 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
508 set_value!(self schema_type schema_type.into())
509 }
510
511 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
513 set_value!(self title title.map(|title| title.into()))
514 }
515
516 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
518 set_value!(self description description.map(|description| description.into()))
519 }
520
521 pub fn default(mut self, default: Option<Value>) -> Self {
523 set_value!(self default default)
524 }
525
526 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
530 pub fn example(mut self, example: Option<Value>) -> Self {
531 set_value!(self example example)
532 }
533
534 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
536 set_value!(self examples examples.into_iter().map(Into::into).collect())
537 }
538
539 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
541 set_value!(self discriminator discriminator)
542 }
543
544 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
546 set_value!(self extensions extensions)
547 }
548
549 pub fn read_only(mut self, read_only: bool) -> Self {
551 set_value!(self read_only Some(read_only))
552 }
553
554 pub fn write_only(mut self, write_only: bool) -> Self {
556 set_value!(self write_only Some(write_only))
557 }
558
559 to_array_builder!();
560}
561
562impl From<OneOf> for Schema {
563 fn from(one_of: OneOf) -> Self {
564 Self::OneOf(one_of)
565 }
566}
567
568impl From<OneOfBuilder> for RefOr<Schema> {
569 fn from(one_of: OneOfBuilder) -> Self {
570 Self::T(Schema::OneOf(one_of.build()))
571 }
572}
573
574impl From<OneOfBuilder> for ArrayItems {
575 fn from(value: OneOfBuilder) -> Self {
576 Self::RefOrSchema(Box::new(value.into()))
577 }
578}
579
580component_from_builder!(OneOfBuilder);
581
582builder! {
583 AllOfBuilder;
584
585 #[derive(Serialize, Deserialize, Clone, PartialEq)]
592 #[cfg_attr(feature = "debug", derive(Debug))]
593 pub struct AllOf {
594 #[serde(rename = "allOf")]
596 pub items: Vec<RefOr<Schema>>,
597
598 #[serde(rename = "type", default = "SchemaType::any", skip_serializing_if = "SchemaType::is_any_value")]
603 pub schema_type: SchemaType,
604
605 #[serde(skip_serializing_if = "Option::is_none")]
607 pub title: Option<String>,
608
609 #[serde(skip_serializing_if = "Option::is_none")]
611 pub description: Option<String>,
612
613 #[serde(skip_serializing_if = "Option::is_none")]
615 pub default: Option<Value>,
616
617 #[serde(skip_serializing_if = "Option::is_none")]
621 pub example: Option<Value>,
622
623 #[serde(skip_serializing_if = "Vec::is_empty", default)]
625 pub examples: Vec<Value>,
626
627 #[serde(skip_serializing_if = "Option::is_none")]
630 pub discriminator: Option<Discriminator>,
631
632 #[serde(skip_serializing_if = "Option::is_none", flatten)]
634 pub extensions: Option<Extensions>,
635 }
636}
637
638impl AllOf {
639 pub fn new() -> Self {
641 Self {
642 ..Default::default()
643 }
644 }
645
646 pub fn with_capacity(capacity: usize) -> Self {
659 Self {
660 items: Vec::with_capacity(capacity),
661 ..Default::default()
662 }
663 }
664}
665
666impl Default for AllOf {
667 fn default() -> Self {
668 Self {
669 items: Default::default(),
670 schema_type: SchemaType::AnyValue,
671 title: Default::default(),
672 description: Default::default(),
673 default: Default::default(),
674 example: Default::default(),
675 examples: Default::default(),
676 discriminator: Default::default(),
677 extensions: Default::default(),
678 }
679 }
680}
681
682impl AllOfBuilder {
683 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
687 self.items.push(component.into());
688
689 self
690 }
691
692 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
695 set_value!(self schema_type schema_type.into())
696 }
697
698 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
700 set_value!(self title title.map(|title| title.into()))
701 }
702
703 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
705 set_value!(self description description.map(|description| description.into()))
706 }
707
708 pub fn default(mut self, default: Option<Value>) -> Self {
710 set_value!(self default default)
711 }
712
713 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
717 pub fn example(mut self, example: Option<Value>) -> Self {
718 set_value!(self example example)
719 }
720
721 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
723 set_value!(self examples examples.into_iter().map(Into::into).collect())
724 }
725
726 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
728 set_value!(self discriminator discriminator)
729 }
730
731 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
733 set_value!(self extensions extensions)
734 }
735
736 to_array_builder!();
737}
738
739impl From<AllOf> for Schema {
740 fn from(one_of: AllOf) -> Self {
741 Self::AllOf(one_of)
742 }
743}
744
745impl From<AllOfBuilder> for RefOr<Schema> {
746 fn from(one_of: AllOfBuilder) -> Self {
747 Self::T(Schema::AllOf(one_of.build()))
748 }
749}
750
751impl From<AllOfBuilder> for ArrayItems {
752 fn from(value: AllOfBuilder) -> Self {
753 Self::RefOrSchema(Box::new(value.into()))
754 }
755}
756
757component_from_builder!(AllOfBuilder);
758
759builder! {
760 AnyOfBuilder;
761
762 #[derive(Serialize, Deserialize, Clone, PartialEq)]
769 #[cfg_attr(feature = "debug", derive(Debug))]
770 pub struct AnyOf {
771 #[serde(rename = "anyOf")]
773 pub items: Vec<RefOr<Schema>>,
774
775 #[serde(rename = "type", default = "SchemaType::any", skip_serializing_if = "SchemaType::is_any_value")]
780 pub schema_type: SchemaType,
781
782 #[serde(skip_serializing_if = "Option::is_none")]
784 pub description: Option<String>,
785
786 #[serde(skip_serializing_if = "Option::is_none")]
788 pub default: Option<Value>,
789
790 #[serde(skip_serializing_if = "Option::is_none")]
794 pub example: Option<Value>,
795
796 #[serde(skip_serializing_if = "Vec::is_empty", default)]
798 pub examples: Vec<Value>,
799
800 #[serde(skip_serializing_if = "Option::is_none")]
803 pub discriminator: Option<Discriminator>,
804
805 #[serde(skip_serializing_if = "Option::is_none", flatten)]
807 pub extensions: Option<Extensions>,
808 }
809}
810
811impl AnyOf {
812 pub fn new() -> Self {
814 Self {
815 ..Default::default()
816 }
817 }
818
819 pub fn with_capacity(capacity: usize) -> Self {
832 Self {
833 items: Vec::with_capacity(capacity),
834 ..Default::default()
835 }
836 }
837}
838
839impl Default for AnyOf {
840 fn default() -> Self {
841 Self {
842 items: Default::default(),
843 schema_type: SchemaType::AnyValue,
844 description: Default::default(),
845 default: Default::default(),
846 example: Default::default(),
847 examples: Default::default(),
848 discriminator: Default::default(),
849 extensions: Default::default(),
850 }
851 }
852}
853
854impl AnyOfBuilder {
855 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
859 self.items.push(component.into());
860
861 self
862 }
863
864 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
867 set_value!(self schema_type schema_type.into())
868 }
869
870 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
872 set_value!(self description description.map(|description| description.into()))
873 }
874
875 pub fn default(mut self, default: Option<Value>) -> Self {
877 set_value!(self default default)
878 }
879
880 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
884 pub fn example(mut self, example: Option<Value>) -> Self {
885 set_value!(self example example)
886 }
887
888 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
890 set_value!(self examples examples.into_iter().map(Into::into).collect())
891 }
892
893 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
895 set_value!(self discriminator discriminator)
896 }
897
898 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
900 set_value!(self extensions extensions)
901 }
902
903 to_array_builder!();
904}
905
906impl From<AnyOf> for Schema {
907 fn from(any_of: AnyOf) -> Self {
908 Self::AnyOf(any_of)
909 }
910}
911
912impl From<AnyOfBuilder> for RefOr<Schema> {
913 fn from(any_of: AnyOfBuilder) -> Self {
914 Self::T(Schema::AnyOf(any_of.build()))
915 }
916}
917
918impl From<AnyOfBuilder> for ArrayItems {
919 fn from(value: AnyOfBuilder) -> Self {
920 Self::RefOrSchema(Box::new(value.into()))
921 }
922}
923
924component_from_builder!(AnyOfBuilder);
925
926#[cfg(not(feature = "preserve_order"))]
927type ObjectPropertiesMap<K, V> = BTreeMap<K, V>;
928#[cfg(feature = "preserve_order")]
929type ObjectPropertiesMap<K, V> = indexmap::IndexMap<K, V>;
930
931builder! {
932 ObjectBuilder;
933
934 #[non_exhaustive]
941 #[derive(Serialize, Deserialize, Default, Clone, PartialEq)]
942 #[cfg_attr(feature = "debug", derive(Debug))]
943 #[serde(rename_all = "camelCase")]
944 pub struct Object {
945 #[serde(rename = "type", skip_serializing_if="SchemaType::is_any_value")]
948 pub schema_type: SchemaType,
949
950 #[serde(skip_serializing_if = "Option::is_none")]
952 pub title: Option<String>,
953
954 #[serde(skip_serializing_if = "Option::is_none")]
956 pub format: Option<SchemaFormat>,
957
958 #[serde(skip_serializing_if = "Option::is_none")]
960 pub description: Option<String>,
961
962 #[serde(skip_serializing_if = "Option::is_none")]
964 pub default: Option<Value>,
965
966 #[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
968 pub enum_values: Option<Vec<Value>>,
969
970 #[serde(skip_serializing_if = "Vec::is_empty", default = "Vec::new")]
972 pub required: Vec<String>,
973
974 #[serde(skip_serializing_if = "ObjectPropertiesMap::is_empty", default = "ObjectPropertiesMap::new")]
982 pub properties: ObjectPropertiesMap<String, RefOr<Schema>>,
983
984 #[serde(skip_serializing_if = "Option::is_none")]
986 pub additional_properties: Option<Box<AdditionalProperties<Schema>>>,
987
988 #[serde(skip_serializing_if = "Option::is_none")]
991 pub property_names: Option<Box<Schema>>,
992
993 #[serde(skip_serializing_if = "Option::is_none")]
995 pub deprecated: Option<Deprecated>,
996
997 #[serde(skip_serializing_if = "Option::is_none")]
1001 pub example: Option<Value>,
1002
1003 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1005 pub examples: Vec<Value>,
1006
1007 #[serde(skip_serializing_if = "Option::is_none")]
1009 pub write_only: Option<bool>,
1010
1011 #[serde(skip_serializing_if = "Option::is_none")]
1013 pub read_only: Option<bool>,
1014
1015 #[serde(skip_serializing_if = "Option::is_none")]
1017 pub xml: Option<Xml>,
1018
1019 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1022 pub multiple_of: Option<crate::utoipa::Number>,
1023
1024 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1027 pub maximum: Option<crate::utoipa::Number>,
1028
1029 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1032 pub minimum: Option<crate::utoipa::Number>,
1033
1034 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1037 pub exclusive_maximum: Option<crate::utoipa::Number>,
1038
1039 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1042 pub exclusive_minimum: Option<crate::utoipa::Number>,
1043
1044 #[serde(skip_serializing_if = "Option::is_none")]
1047 pub max_length: Option<usize>,
1048
1049 #[serde(skip_serializing_if = "Option::is_none")]
1053 pub min_length: Option<usize>,
1054
1055 #[serde(skip_serializing_if = "Option::is_none")]
1058 pub pattern: Option<String>,
1059
1060 #[serde(skip_serializing_if = "Option::is_none")]
1062 pub max_properties: Option<usize>,
1063
1064 #[serde(skip_serializing_if = "Option::is_none")]
1067 pub min_properties: Option<usize>,
1068
1069 #[serde(skip_serializing_if = "Option::is_none", flatten)]
1071 pub extensions: Option<Extensions>,
1072
1073 #[serde(skip_serializing_if = "String::is_empty", default)]
1082 pub content_encoding: String,
1083
1084 #[serde(skip_serializing_if = "String::is_empty", default)]
1089 pub content_media_type: String,
1090 }
1091}
1092
1093fn is_false(value: &bool) -> bool {
1094 !*value
1095}
1096
1097impl Object {
1098 pub fn new() -> Self {
1101 Self {
1102 ..Default::default()
1103 }
1104 }
1105
1106 pub fn with_type<T: Into<SchemaType>>(schema_type: T) -> Self {
1114 Self {
1115 schema_type: schema_type.into(),
1116 ..Default::default()
1117 }
1118 }
1119}
1120
1121impl From<Object> for Schema {
1122 fn from(s: Object) -> Self {
1123 Self::Object(s)
1124 }
1125}
1126
1127impl From<Object> for ArrayItems {
1128 fn from(value: Object) -> Self {
1129 Self::RefOrSchema(Box::new(value.into()))
1130 }
1131}
1132
1133impl ToArray for Object {}
1134
1135impl ObjectBuilder {
1136 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
1139 set_value!(self schema_type schema_type.into())
1140 }
1141
1142 pub fn format(mut self, format: Option<SchemaFormat>) -> Self {
1144 set_value!(self format format)
1145 }
1146
1147 pub fn property<S: Into<String>, I: Into<RefOr<Schema>>>(
1151 mut self,
1152 property_name: S,
1153 component: I,
1154 ) -> Self {
1155 self.properties
1156 .insert(property_name.into(), component.into());
1157
1158 self
1159 }
1160
1161 pub fn additional_properties<I: Into<AdditionalProperties<Schema>>>(
1163 mut self,
1164 additional_properties: Option<I>,
1165 ) -> Self {
1166 set_value!(self additional_properties additional_properties.map(|additional_properties| Box::new(additional_properties.into())))
1167 }
1168
1169 pub fn property_names<S: Into<Schema>>(mut self, property_name: Option<S>) -> Self {
1172 set_value!(self property_names property_name.map(|property_name| Box::new(property_name.into())))
1173 }
1174
1175 pub fn required<I: Into<String>>(mut self, required_field: I) -> Self {
1177 self.required.push(required_field.into());
1178
1179 self
1180 }
1181
1182 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
1184 set_value!(self title title.map(|title| title.into()))
1185 }
1186
1187 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
1189 set_value!(self description description.map(|description| description.into()))
1190 }
1191
1192 pub fn default(mut self, default: Option<Value>) -> Self {
1194 set_value!(self default default)
1195 }
1196
1197 pub fn deprecated(mut self, deprecated: Option<Deprecated>) -> Self {
1199 set_value!(self deprecated deprecated)
1200 }
1201
1202 pub fn enum_values<I: IntoIterator<Item = E>, E: Into<Value>>(
1204 mut self,
1205 enum_values: Option<I>,
1206 ) -> Self {
1207 set_value!(self enum_values
1208 enum_values.map(|values| values.into_iter().map(|enum_value| enum_value.into()).collect()))
1209 }
1210
1211 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
1215 pub fn example(mut self, example: Option<Value>) -> Self {
1216 set_value!(self example example)
1217 }
1218
1219 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
1221 set_value!(self examples examples.into_iter().map(Into::into).collect())
1222 }
1223
1224 pub fn write_only(mut self, write_only: bool) -> Self {
1226 set_value!(self write_only Some(write_only))
1227 }
1228
1229 pub fn read_only(mut self, read_only: bool) -> Self {
1231 set_value!(self read_only Some(read_only))
1232 }
1233
1234 pub fn xml(mut self, xml: Option<Xml>) -> Self {
1236 set_value!(self xml xml)
1237 }
1238
1239 pub fn multiple_of<N: Into<crate::utoipa::Number>>(mut self, multiple_of: Option<N>) -> Self {
1241 set_value!(self multiple_of multiple_of.map(|multiple_of| multiple_of.into()))
1242 }
1243
1244 pub fn maximum<N: Into<crate::utoipa::Number>>(mut self, maximum: Option<N>) -> Self {
1246 set_value!(self maximum maximum.map(|max| max.into()))
1247 }
1248
1249 pub fn minimum<N: Into<crate::utoipa::Number>>(mut self, minimum: Option<N>) -> Self {
1251 set_value!(self minimum minimum.map(|min| min.into()))
1252 }
1253
1254 pub fn exclusive_maximum<N: Into<crate::utoipa::Number>>(
1256 mut self,
1257 exclusive_maximum: Option<N>,
1258 ) -> Self {
1259 set_value!(self exclusive_maximum exclusive_maximum.map(|exclusive_maximum| exclusive_maximum.into()))
1260 }
1261
1262 pub fn exclusive_minimum<N: Into<crate::utoipa::Number>>(
1264 mut self,
1265 exclusive_minimum: Option<N>,
1266 ) -> Self {
1267 set_value!(self exclusive_minimum exclusive_minimum.map(|exclusive_minimum| exclusive_minimum.into()))
1268 }
1269
1270 pub fn max_length(mut self, max_length: Option<usize>) -> Self {
1272 set_value!(self max_length max_length)
1273 }
1274
1275 pub fn min_length(mut self, min_length: Option<usize>) -> Self {
1277 set_value!(self min_length min_length)
1278 }
1279
1280 pub fn pattern<I: Into<String>>(mut self, pattern: Option<I>) -> Self {
1282 set_value!(self pattern pattern.map(|pattern| pattern.into()))
1283 }
1284
1285 pub fn max_properties(mut self, max_properties: Option<usize>) -> Self {
1287 set_value!(self max_properties max_properties)
1288 }
1289
1290 pub fn min_properties(mut self, min_properties: Option<usize>) -> Self {
1292 set_value!(self min_properties min_properties)
1293 }
1294
1295 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
1297 set_value!(self extensions extensions)
1298 }
1299
1300 pub fn content_encoding<S: Into<String>>(mut self, content_encoding: S) -> Self {
1303 set_value!(self content_encoding content_encoding.into())
1304 }
1305
1306 pub fn content_media_type<S: Into<String>>(mut self, content_media_type: S) -> Self {
1309 set_value!(self content_media_type content_media_type.into())
1310 }
1311
1312 to_array_builder!();
1313}
1314
1315component_from_builder!(ObjectBuilder);
1316
1317impl From<ObjectBuilder> for RefOr<Schema> {
1318 fn from(builder: ObjectBuilder) -> Self {
1319 Self::T(Schema::Object(builder.build()))
1320 }
1321}
1322
1323impl From<RefOr<Schema>> for Schema {
1324 fn from(value: RefOr<Schema>) -> Self {
1325 match value {
1326 RefOr::Ref(_) => {
1327 panic!("Invalid type `RefOr::Ref` provided, cannot convert to RefOr::T<Schema>")
1328 }
1329 RefOr::T(value) => value,
1330 }
1331 }
1332}
1333
1334impl From<ObjectBuilder> for ArrayItems {
1335 fn from(value: ObjectBuilder) -> Self {
1336 Self::RefOrSchema(Box::new(value.into()))
1337 }
1338}
1339
1340#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1344#[cfg_attr(feature = "debug", derive(Debug))]
1345#[serde(untagged)]
1346pub enum AdditionalProperties<T> {
1347 RefOr(RefOr<T>),
1349 FreeForm(bool),
1351}
1352
1353impl<T> From<RefOr<T>> for AdditionalProperties<T> {
1354 fn from(value: RefOr<T>) -> Self {
1355 Self::RefOr(value)
1356 }
1357}
1358
1359impl From<ObjectBuilder> for AdditionalProperties<Schema> {
1360 fn from(value: ObjectBuilder) -> Self {
1361 Self::RefOr(RefOr::T(Schema::Object(value.build())))
1362 }
1363}
1364
1365impl From<ArrayBuilder> for AdditionalProperties<Schema> {
1366 fn from(value: ArrayBuilder) -> Self {
1367 Self::RefOr(RefOr::T(Schema::Array(value.build())))
1368 }
1369}
1370
1371impl From<Ref> for AdditionalProperties<Schema> {
1372 fn from(value: Ref) -> Self {
1373 Self::RefOr(RefOr::Ref(value))
1374 }
1375}
1376
1377impl From<RefBuilder> for AdditionalProperties<Schema> {
1378 fn from(value: RefBuilder) -> Self {
1379 Self::RefOr(RefOr::Ref(value.build()))
1380 }
1381}
1382
1383impl From<Schema> for AdditionalProperties<Schema> {
1384 fn from(value: Schema) -> Self {
1385 Self::RefOr(RefOr::T(value))
1386 }
1387}
1388
1389impl From<AllOfBuilder> for AdditionalProperties<Schema> {
1390 fn from(value: AllOfBuilder) -> Self {
1391 Self::RefOr(RefOr::T(Schema::AllOf(value.build())))
1392 }
1393}
1394
1395builder! {
1396 RefBuilder;
1397
1398 #[non_exhaustive]
1403 #[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq)]
1404 #[cfg_attr(feature = "debug", derive(Debug))]
1405 pub struct Ref {
1406 #[serde(rename = "$ref")]
1408 pub ref_location: String,
1409
1410 #[serde(skip_serializing_if = "String::is_empty", default)]
1414 pub description: String,
1415
1416 #[serde(skip_serializing_if = "String::is_empty", default)]
1419 pub summary: String,
1420
1421 #[serde(rename = "readOnly", skip_serializing_if = "Option::is_none")]
1426 pub read_only: Option<bool>,
1427
1428 #[serde(rename = "writeOnly", skip_serializing_if = "Option::is_none")]
1433 pub write_only: Option<bool>,
1434
1435 #[serde(skip_serializing_if = "Option::is_none")]
1437 pub default: Option<Value>,
1438
1439 #[serde(skip_serializing_if = "Option::is_none")]
1441 pub title: Option<String>,
1442 }
1443}
1444
1445impl Ref {
1446 pub fn new<I: Into<String>>(ref_location: I) -> Self {
1449 Self {
1450 ref_location: ref_location.into(),
1451 ..Default::default()
1452 }
1453 }
1454
1455 pub fn from_schema_name<I: Into<String>>(schema_name: I) -> Self {
1458 Self::new(format!("#/components/schemas/{}", schema_name.into()))
1459 }
1460
1461 pub fn from_response_name<I: Into<String>>(response_name: I) -> Self {
1464 Self::new(format!("#/components/responses/{}", response_name.into()))
1465 }
1466
1467 to_array_builder!();
1468}
1469
1470impl RefBuilder {
1471 pub fn ref_location(mut self, ref_location: String) -> Self {
1473 set_value!(self ref_location ref_location)
1474 }
1475
1476 pub fn ref_location_from_schema_name<S: Into<String>>(mut self, schema_name: S) -> Self {
1479 set_value!(self ref_location format!("#/components/schemas/{}", schema_name.into()))
1480 }
1481
1482 pub fn description<S: Into<String>>(mut self, description: Option<S>) -> Self {
1488 set_value!(self description description.map(Into::into).unwrap_or_default())
1489 }
1490
1491 pub fn summary<S: Into<String>>(mut self, summary: S) -> Self {
1494 set_value!(self summary summary.into())
1495 }
1496
1497 pub fn read_only(mut self, read_only: bool) -> Self {
1499 set_value!(self read_only Some(read_only))
1500 }
1501
1502 pub fn write_only(mut self, write_only: bool) -> Self {
1504 set_value!(self write_only Some(write_only))
1505 }
1506
1507 pub fn default(mut self, default: Option<Value>) -> Self {
1509 set_value!(self default default)
1510 }
1511
1512 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
1514 set_value!(self title title.map(|title| title.into()))
1515 }
1516}
1517
1518impl From<RefBuilder> for RefOr<Schema> {
1519 fn from(builder: RefBuilder) -> Self {
1520 Self::Ref(builder.build())
1521 }
1522}
1523
1524impl From<RefBuilder> for ArrayItems {
1525 fn from(value: RefBuilder) -> Self {
1526 Self::RefOrSchema(Box::new(value.into()))
1527 }
1528}
1529
1530impl From<Ref> for RefOr<Schema> {
1531 fn from(r: Ref) -> Self {
1532 Self::Ref(r)
1533 }
1534}
1535
1536impl From<Ref> for ArrayItems {
1537 fn from(value: Ref) -> Self {
1538 Self::RefOrSchema(Box::new(value.into()))
1539 }
1540}
1541
1542impl<T> From<T> for RefOr<T> {
1543 fn from(t: T) -> Self {
1544 Self::T(t)
1545 }
1546}
1547
1548impl Default for RefOr<Schema> {
1549 fn default() -> Self {
1550 Self::T(Schema::Object(Object::new()))
1551 }
1552}
1553
1554impl ToArray for RefOr<Schema> {}
1555
1556impl From<Object> for RefOr<Schema> {
1557 fn from(object: Object) -> Self {
1558 Self::T(Schema::Object(object))
1559 }
1560}
1561
1562impl From<Array> for RefOr<Schema> {
1563 fn from(array: Array) -> Self {
1564 Self::T(Schema::Array(array))
1565 }
1566}
1567
1568fn omit_decimal_zero<S>(
1569 maybe_value: &Option<crate::utoipa::Number>,
1570 serializer: S,
1571) -> Result<S::Ok, S::Error>
1572where
1573 S: serde::Serializer,
1574{
1575 match maybe_value {
1576 Some(crate::utoipa::Number::Float(float)) => {
1577 if float.fract() == 0.0 && *float >= i64::MIN as f64 && *float <= i64::MAX as f64 {
1578 serializer.serialize_i64(float.trunc() as i64)
1579 } else {
1580 serializer.serialize_f64(*float)
1581 }
1582 }
1583 Some(crate::utoipa::Number::Int(int)) => serializer.serialize_i64(*int as i64),
1584 Some(crate::utoipa::Number::UInt(uint)) => serializer.serialize_u64(*uint as u64),
1585 None => serializer.serialize_none(),
1586 }
1587}
1588
1589#[derive(Serialize, Deserialize, Clone, PartialEq)]
1593#[cfg_attr(feature = "debug", derive(Debug))]
1594#[serde(untagged)]
1595pub enum ArrayItems {
1596 RefOrSchema(Box<RefOr<Schema>>),
1598 #[serde(with = "array_items_false")]
1604 False,
1605}
1606
1607mod array_items_false {
1608 use serde::de::Visitor;
1609
1610 pub fn serialize<S: serde::Serializer>(serializer: S) -> Result<S::Ok, S::Error> {
1611 serializer.serialize_bool(false)
1612 }
1613
1614 pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<(), D::Error> {
1615 struct ItemsFalseVisitor;
1616
1617 impl<'de> Visitor<'de> for ItemsFalseVisitor {
1618 type Value = ();
1619 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
1620 where
1621 E: serde::de::Error,
1622 {
1623 if !v {
1624 Ok(())
1625 } else {
1626 Err(serde::de::Error::custom(format!(
1627 "invalid boolean value: {v}, expected false"
1628 )))
1629 }
1630 }
1631
1632 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1633 formatter.write_str("expected boolean false")
1634 }
1635 }
1636
1637 deserializer.deserialize_bool(ItemsFalseVisitor)
1638 }
1639}
1640
1641impl Default for ArrayItems {
1642 fn default() -> Self {
1643 Self::RefOrSchema(Box::new(Object::with_type(SchemaType::AnyValue).into()))
1644 }
1645}
1646
1647impl From<RefOr<Schema>> for ArrayItems {
1648 fn from(value: RefOr<Schema>) -> Self {
1649 Self::RefOrSchema(Box::new(value))
1650 }
1651}
1652
1653builder! {
1654 ArrayBuilder;
1655
1656 #[non_exhaustive]
1660 #[derive(Serialize, Deserialize, Clone, PartialEq)]
1661 #[cfg_attr(feature = "debug", derive(Debug))]
1662 #[serde(rename_all = "camelCase")]
1663 pub struct Array {
1664 #[serde(rename = "type")]
1666 pub schema_type: SchemaType,
1667
1668 #[serde(skip_serializing_if = "Option::is_none")]
1670 pub title: Option<String>,
1671
1672 pub items: ArrayItems,
1674
1675 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1680 pub prefix_items: Vec<Schema>,
1681
1682 #[serde(skip_serializing_if = "Option::is_none")]
1684 pub description: Option<String>,
1685
1686 #[serde(skip_serializing_if = "Option::is_none")]
1688 pub deprecated: Option<Deprecated>,
1689
1690 #[serde(skip_serializing_if = "Option::is_none")]
1694 pub example: Option<Value>,
1695
1696 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1698 pub examples: Vec<Value>,
1699
1700 #[serde(skip_serializing_if = "Option::is_none")]
1702 pub default: Option<Value>,
1703
1704 #[serde(skip_serializing_if = "Option::is_none")]
1706 pub max_items: Option<usize>,
1707
1708 #[serde(skip_serializing_if = "Option::is_none")]
1710 pub min_items: Option<usize>,
1711
1712 #[serde(default, skip_serializing_if = "is_false")]
1715 pub unique_items: bool,
1716
1717 #[serde(skip_serializing_if = "Option::is_none")]
1719 pub xml: Option<Xml>,
1720
1721 #[serde(skip_serializing_if = "String::is_empty", default)]
1730 pub content_encoding: String,
1731
1732 #[serde(skip_serializing_if = "String::is_empty", default)]
1737 pub content_media_type: String,
1738
1739 #[serde(skip_serializing_if = "Option::is_none", flatten)]
1741 pub extensions: Option<Extensions>,
1742 }
1743}
1744
1745impl Default for Array {
1746 fn default() -> Self {
1747 Self {
1748 title: Default::default(),
1749 schema_type: Type::Array.into(),
1750 unique_items: bool::default(),
1751 items: Default::default(),
1752 prefix_items: Vec::default(),
1753 description: Default::default(),
1754 deprecated: Default::default(),
1755 example: Default::default(),
1756 examples: Default::default(),
1757 default: Default::default(),
1758 max_items: Default::default(),
1759 min_items: Default::default(),
1760 xml: Default::default(),
1761 extensions: Default::default(),
1762 content_encoding: Default::default(),
1763 content_media_type: Default::default(),
1764 }
1765 }
1766}
1767
1768impl Array {
1769 pub fn new<I: Into<RefOr<Schema>>>(component: I) -> Self {
1779 Self {
1780 items: ArrayItems::RefOrSchema(Box::new(component.into())),
1781 ..Default::default()
1782 }
1783 }
1784
1785 pub fn new_nullable<I: Into<RefOr<Schema>>>(component: I) -> Self {
1795 Self {
1796 items: ArrayItems::RefOrSchema(Box::new(component.into())),
1797 schema_type: SchemaType::from_iter([Type::Array, Type::Null]),
1798 ..Default::default()
1799 }
1800 }
1801}
1802
1803impl ArrayBuilder {
1804 pub fn items<I: Into<ArrayItems>>(mut self, items: I) -> Self {
1806 set_value!(self items items.into())
1807 }
1808
1809 pub fn prefix_items<I: IntoIterator<Item = S>, S: Into<Schema>>(mut self, items: I) -> Self {
1814 self.prefix_items = items
1815 .into_iter()
1816 .map(|item| item.into())
1817 .collect::<Vec<_>>();
1818
1819 self
1820 }
1821
1822 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
1836 set_value!(self schema_type schema_type.into())
1837 }
1838
1839 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
1841 set_value!(self title title.map(|title| title.into()))
1842 }
1843
1844 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
1846 set_value!(self description description.map(|description| description.into()))
1847 }
1848
1849 pub fn deprecated(mut self, deprecated: Option<Deprecated>) -> Self {
1851 set_value!(self deprecated deprecated)
1852 }
1853
1854 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
1858 pub fn example(mut self, example: Option<Value>) -> Self {
1859 set_value!(self example example)
1860 }
1861
1862 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
1864 set_value!(self examples examples.into_iter().map(Into::into).collect())
1865 }
1866
1867 pub fn default(mut self, default: Option<Value>) -> Self {
1869 set_value!(self default default)
1870 }
1871
1872 pub fn max_items(mut self, max_items: Option<usize>) -> Self {
1874 set_value!(self max_items max_items)
1875 }
1876
1877 pub fn min_items(mut self, min_items: Option<usize>) -> Self {
1879 set_value!(self min_items min_items)
1880 }
1881
1882 pub fn unique_items(mut self, unique_items: bool) -> Self {
1884 set_value!(self unique_items unique_items)
1885 }
1886
1887 pub fn xml(mut self, xml: Option<Xml>) -> Self {
1889 set_value!(self xml xml)
1890 }
1891
1892 pub fn content_encoding<S: Into<String>>(mut self, content_encoding: S) -> Self {
1895 set_value!(self content_encoding content_encoding.into())
1896 }
1897
1898 pub fn content_media_type<S: Into<String>>(mut self, content_media_type: S) -> Self {
1901 set_value!(self content_media_type content_media_type.into())
1902 }
1903
1904 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
1906 set_value!(self extensions extensions)
1907 }
1908
1909 to_array_builder!();
1910}
1911
1912component_from_builder!(ArrayBuilder);
1913
1914impl From<Array> for Schema {
1915 fn from(array: Array) -> Self {
1916 Self::Array(array)
1917 }
1918}
1919
1920impl From<ArrayBuilder> for ArrayItems {
1921 fn from(value: ArrayBuilder) -> Self {
1922 Self::RefOrSchema(Box::new(value.into()))
1923 }
1924}
1925
1926impl From<ArrayBuilder> for RefOr<Schema> {
1927 fn from(array: ArrayBuilder) -> Self {
1928 Self::T(Schema::Array(array.build()))
1929 }
1930}
1931
1932impl ToArray for Array {}
1933
1934pub trait ToArray
1936where
1937 RefOr<Schema>: From<Self>,
1938 Self: Sized,
1939{
1940 fn to_array(self) -> Array {
1942 Array::new(self)
1943 }
1944}
1945
1946#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1951#[cfg_attr(feature = "debug", derive(Debug))]
1952#[serde(untagged)]
1953pub enum SchemaType {
1954 Type(Type),
1956 Array(Vec<Type>),
1958 AnyValue,
1961}
1962
1963impl Default for SchemaType {
1964 fn default() -> Self {
1965 Self::Type(Type::default())
1966 }
1967}
1968
1969impl From<Type> for SchemaType {
1970 fn from(value: Type) -> Self {
1971 SchemaType::new(value)
1972 }
1973}
1974
1975impl FromIterator<Type> for SchemaType {
1976 fn from_iter<T: IntoIterator<Item = Type>>(iter: T) -> Self {
1977 Self::Array(iter.into_iter().collect())
1978 }
1979}
1980
1981impl SchemaType {
1982 pub fn new(r#type: Type) -> Self {
1994 Self::Type(r#type)
1995 }
1996
1997 pub fn any() -> Self {
2002 SchemaType::AnyValue
2003 }
2004
2005 pub fn is_any_value(&self) -> bool {
2008 matches!(self, Self::AnyValue)
2009 }
2010}
2011
2012#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
2032#[cfg_attr(feature = "debug", derive(Debug))]
2033#[serde(rename_all = "lowercase")]
2034pub enum Type {
2035 #[default]
2038 Object,
2039 String,
2042 Integer,
2045 Number,
2048 Boolean,
2051 Array,
2053 Null,
2055}
2056
2057#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
2062#[cfg_attr(feature = "debug", derive(Debug))]
2063#[serde(rename_all = "lowercase", untagged)]
2064pub enum SchemaFormat {
2065 KnownFormat(KnownFormat),
2067 Custom(String),
2070}
2071
2072#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
2078#[cfg_attr(feature = "debug", derive(Debug))]
2079#[serde(rename_all = "kebab-case")]
2080pub enum KnownFormat {
2081 #[cfg(feature = "non_strict_integers")]
2083 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2084 Int8,
2085 #[cfg(feature = "non_strict_integers")]
2087 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2088 Int16,
2089 Int32,
2091 Int64,
2093 #[cfg(feature = "non_strict_integers")]
2095 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2096 UInt8,
2097 #[cfg(feature = "non_strict_integers")]
2099 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2100 UInt16,
2101 #[cfg(feature = "non_strict_integers")]
2103 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2104 UInt32,
2105 #[cfg(feature = "non_strict_integers")]
2107 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2108 UInt64,
2109 Float,
2111 Double,
2113 Byte,
2115 Binary,
2117 Time,
2119 Date,
2121 DateTime,
2123 Duration,
2125 Password,
2127 #[cfg(feature = "uuid")]
2131 #[cfg_attr(doc_cfg, doc(cfg(feature = "uuid")))]
2132 Uuid,
2133 #[cfg(feature = "ulid")]
2135 #[cfg_attr(doc_cfg, doc(cfg(feature = "ulid")))]
2136 Ulid,
2137 #[cfg(feature = "url")]
2140 #[cfg_attr(doc_cfg, doc(cfg(feature = "url")))]
2141 Uri,
2142 #[cfg(feature = "url")]
2146 #[cfg_attr(doc_cfg, doc(cfg(feature = "url")))]
2147 UriReference,
2148 #[cfg(feature = "url")]
2151 #[cfg_attr(doc_cfg, doc(cfg(feature = "url")))]
2152 Iri,
2153 #[cfg(feature = "url")]
2157 #[cfg_attr(doc_cfg, doc(cfg(feature = "url")))]
2158 IriReference,
2159 Email,
2161 IdnEmail,
2163 Hostname,
2167 IdnHostname,
2170 Ipv4,
2172 Ipv6,
2174 UriTemplate,
2179 JsonPointer,
2181 RelativeJsonPointer,
2183 Regex,
2186}
2187
2188#[cfg(test)]
2189mod tests {
2190 use insta::assert_json_snapshot;
2191 use serde_json::{json, Value};
2192
2193 use super::*;
2194 use crate::openapi::*;
2195
2196 #[test]
2197 fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
2198 let openapi = OpenApiBuilder::new()
2199 .info(Info::new("My api", "1.0.0"))
2200 .paths(Paths::new())
2201 .components(Some(
2202 ComponentsBuilder::new()
2203 .schema("Person", Ref::new("#/components/PersonModel"))
2204 .schema(
2205 "Credential",
2206 Schema::from(
2207 ObjectBuilder::new()
2208 .property(
2209 "id",
2210 ObjectBuilder::new()
2211 .schema_type(Type::Integer)
2212 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2213 .description(Some("Id of credential"))
2214 .default(Some(json!(1i32))),
2215 )
2216 .property(
2217 "name",
2218 ObjectBuilder::new()
2219 .schema_type(Type::String)
2220 .description(Some("Name of credential")),
2221 )
2222 .property(
2223 "status",
2224 ObjectBuilder::new()
2225 .schema_type(Type::String)
2226 .default(Some(json!("Active")))
2227 .description(Some("Credential status"))
2228 .enum_values(Some([
2229 "Active",
2230 "NotActive",
2231 "Locked",
2232 "Expired",
2233 ])),
2234 )
2235 .property(
2236 "history",
2237 Array::new(Ref::from_schema_name("UpdateHistory")),
2238 )
2239 .property("tags", Object::with_type(Type::String).to_array()),
2240 ),
2241 )
2242 .build(),
2243 ))
2244 .build();
2245
2246 let serialized = serde_json::to_string_pretty(&openapi)?;
2247 println!("serialized json:\n {serialized}");
2248
2249 let value = serde_json::to_value(&openapi)?;
2250 let credential = get_json_path(&value, "components.schemas.Credential.properties");
2251 let person = get_json_path(&value, "components.schemas.Person");
2252
2253 assert!(
2254 credential.get("id").is_some(),
2255 "could not find path: components.schemas.Credential.properties.id"
2256 );
2257 assert!(
2258 credential.get("status").is_some(),
2259 "could not find path: components.schemas.Credential.properties.status"
2260 );
2261 assert!(
2262 credential.get("name").is_some(),
2263 "could not find path: components.schemas.Credential.properties.name"
2264 );
2265 assert!(
2266 credential.get("history").is_some(),
2267 "could not find path: components.schemas.Credential.properties.history"
2268 );
2269 assert_eq!(
2270 credential
2271 .get("id")
2272 .unwrap_or(&serde_json::value::Value::Null)
2273 .to_string(),
2274 r#"{"default":1,"description":"Id of credential","format":"int32","type":"integer"}"#,
2275 "components.schemas.Credential.properties.id did not match"
2276 );
2277 assert_eq!(
2278 credential
2279 .get("name")
2280 .unwrap_or(&serde_json::value::Value::Null)
2281 .to_string(),
2282 r#"{"description":"Name of credential","type":"string"}"#,
2283 "components.schemas.Credential.properties.name did not match"
2284 );
2285 assert_eq!(
2286 credential
2287 .get("status")
2288 .unwrap_or(&serde_json::value::Value::Null)
2289 .to_string(),
2290 r#"{"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"}"#,
2291 "components.schemas.Credential.properties.status did not match"
2292 );
2293 assert_eq!(
2294 credential
2295 .get("history")
2296 .unwrap_or(&serde_json::value::Value::Null)
2297 .to_string(),
2298 r###"{"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"}"###,
2299 "components.schemas.Credential.properties.history did not match"
2300 );
2301 assert_eq!(
2302 person.to_string(),
2303 r###"{"$ref":"#/components/PersonModel"}"###,
2304 "components.schemas.Person.ref did not match"
2305 );
2306
2307 Ok(())
2308 }
2309
2310 #[test]
2312 fn test_property_order() {
2313 let json_value = ObjectBuilder::new()
2314 .property(
2315 "id",
2316 ObjectBuilder::new()
2317 .schema_type(Type::Integer)
2318 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2319 .description(Some("Id of credential"))
2320 .default(Some(json!(1i32))),
2321 )
2322 .property(
2323 "name",
2324 ObjectBuilder::new()
2325 .schema_type(Type::String)
2326 .description(Some("Name of credential")),
2327 )
2328 .property(
2329 "status",
2330 ObjectBuilder::new()
2331 .schema_type(Type::String)
2332 .default(Some(json!("Active")))
2333 .description(Some("Credential status"))
2334 .enum_values(Some(["Active", "NotActive", "Locked", "Expired"])),
2335 )
2336 .property(
2337 "history",
2338 Array::new(Ref::from_schema_name("UpdateHistory")),
2339 )
2340 .property("tags", Object::with_type(Type::String).to_array())
2341 .build();
2342
2343 #[cfg(not(feature = "preserve_order"))]
2344 assert_eq!(
2345 json_value.properties.keys().collect::<Vec<_>>(),
2346 vec!["history", "id", "name", "status", "tags"]
2347 );
2348
2349 #[cfg(feature = "preserve_order")]
2350 assert_eq!(
2351 json_value.properties.keys().collect::<Vec<_>>(),
2352 vec!["id", "name", "status", "history", "tags"]
2353 );
2354 }
2355
2356 #[test]
2358 fn test_additional_properties() {
2359 let json_value = ObjectBuilder::new()
2360 .additional_properties(Some(ObjectBuilder::new().schema_type(Type::String)))
2361 .build();
2362 assert_json_snapshot!(json_value, @r#"
2363 {
2364 "type": "object",
2365 "additionalProperties": {
2366 "type": "string"
2367 }
2368 }
2369 "#);
2370
2371 let json_value = ObjectBuilder::new()
2372 .additional_properties(Some(ArrayBuilder::new().items(ArrayItems::RefOrSchema(
2373 Box::new(ObjectBuilder::new().schema_type(Type::Number).into()),
2374 ))))
2375 .build();
2376 assert_json_snapshot!(json_value, @r#"
2377 {
2378 "type": "object",
2379 "additionalProperties": {
2380 "type": "array",
2381 "items": {
2382 "type": "number"
2383 }
2384 }
2385 }
2386 "#);
2387
2388 let json_value = ObjectBuilder::new()
2389 .additional_properties(Some(Ref::from_schema_name("ComplexModel")))
2390 .build();
2391 assert_json_snapshot!(json_value, @r##"
2392 {
2393 "type": "object",
2394 "additionalProperties": {
2395 "$ref": "#/components/schemas/ComplexModel"
2396 }
2397 }
2398 "##);
2399 }
2400
2401 #[test]
2402 fn test_object_with_title() {
2403 let json_value = ObjectBuilder::new().title(Some("SomeName")).build();
2404 assert_json_snapshot!(json_value, @r#"
2405 {
2406 "type": "object",
2407 "title": "SomeName"
2408 }
2409 "#);
2410 }
2411
2412 #[test]
2413 fn derive_object_with_examples() {
2414 let json_value = ObjectBuilder::new()
2415 .examples([Some(json!({"age": 20, "name": "bob the cat"}))])
2416 .build();
2417 assert_json_snapshot!(json_value, @r#"
2418 {
2419 "type": "object",
2420 "examples": [
2421 {
2422 "age": 20,
2423 "name": "bob the cat"
2424 }
2425 ]
2426 }
2427 "#);
2428 }
2429
2430 fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
2431 path.split('.').fold(value, |acc, fragment| {
2432 acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
2433 })
2434 }
2435
2436 #[test]
2437 fn test_array_new() {
2438 let array = Array::new(
2439 ObjectBuilder::new().property(
2440 "id",
2441 ObjectBuilder::new()
2442 .schema_type(Type::Integer)
2443 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2444 .description(Some("Id of credential"))
2445 .default(Some(json!(1i32))),
2446 ),
2447 );
2448
2449 assert!(matches!(array.schema_type, SchemaType::Type(Type::Array)));
2450 }
2451
2452 #[test]
2453 fn test_array_builder() {
2454 let array: Array = ArrayBuilder::new()
2455 .items(
2456 ObjectBuilder::new().property(
2457 "id",
2458 ObjectBuilder::new()
2459 .schema_type(Type::Integer)
2460 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2461 .description(Some("Id of credential"))
2462 .default(Some(json!(1i32))),
2463 ),
2464 )
2465 .build();
2466
2467 assert!(matches!(array.schema_type, SchemaType::Type(Type::Array)));
2468 }
2469
2470 #[test]
2471 fn reserialize_deserialized_schema_components() {
2472 let components = ComponentsBuilder::new()
2473 .schemas_from_iter(vec![(
2474 "Comp",
2475 Schema::from(
2476 ObjectBuilder::new()
2477 .property("name", ObjectBuilder::new().schema_type(Type::String))
2478 .required("name"),
2479 ),
2480 )])
2481 .responses_from_iter(vec![(
2482 "200",
2483 ResponseBuilder::new().description("Okay").build(),
2484 )])
2485 .security_scheme(
2486 "TLS",
2487 SecurityScheme::MutualTls {
2488 description: None,
2489 extensions: None,
2490 },
2491 )
2492 .build();
2493
2494 let serialized_components = serde_json::to_string(&components).unwrap();
2495
2496 let deserialized_components: Components =
2497 serde_json::from_str(serialized_components.as_str()).unwrap();
2498
2499 assert_eq!(
2500 serialized_components,
2501 serde_json::to_string(&deserialized_components).unwrap()
2502 )
2503 }
2504
2505 #[test]
2506 fn reserialize_deserialized_object_component() {
2507 let prop = ObjectBuilder::new()
2508 .property("name", ObjectBuilder::new().schema_type(Type::String))
2509 .required("name")
2510 .build();
2511
2512 let serialized_components = serde_json::to_string(&prop).unwrap();
2513 let deserialized_components: Object =
2514 serde_json::from_str(serialized_components.as_str()).unwrap();
2515
2516 assert_eq!(
2517 serialized_components,
2518 serde_json::to_string(&deserialized_components).unwrap()
2519 )
2520 }
2521
2522 #[test]
2523 fn reserialize_deserialized_property() {
2524 let prop = ObjectBuilder::new().schema_type(Type::String).build();
2525
2526 let serialized_components = serde_json::to_string(&prop).unwrap();
2527 let deserialized_components: Object =
2528 serde_json::from_str(serialized_components.as_str()).unwrap();
2529
2530 assert_eq!(
2531 serialized_components,
2532 serde_json::to_string(&deserialized_components).unwrap()
2533 )
2534 }
2535
2536 #[test]
2537 fn serialize_deserialize_array_within_ref_or_t_object_builder() {
2538 let ref_or_schema = RefOr::T(Schema::Object(
2539 ObjectBuilder::new()
2540 .property(
2541 "test",
2542 RefOr::T(Schema::Array(
2543 ArrayBuilder::new()
2544 .items(RefOr::T(Schema::Object(
2545 ObjectBuilder::new()
2546 .property("element", RefOr::Ref(Ref::new("#/test")))
2547 .build(),
2548 )))
2549 .build(),
2550 )),
2551 )
2552 .build(),
2553 ));
2554
2555 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2556 println!("----------------------------");
2557 println!("{json_str}");
2558
2559 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2560
2561 let json_de_str = serde_json::to_string(&deserialized).expect("");
2562 println!("----------------------------");
2563 println!("{json_de_str}");
2564
2565 assert_eq!(json_str, json_de_str);
2566 }
2567
2568 #[test]
2569 fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
2570 let ref_or_schema = RefOr::T(Schema::Object(
2571 ObjectBuilder::new()
2572 .property(
2573 "test",
2574 RefOr::T(Schema::OneOf(
2575 OneOfBuilder::new()
2576 .item(Schema::Array(
2577 ArrayBuilder::new()
2578 .items(RefOr::T(Schema::Object(
2579 ObjectBuilder::new()
2580 .property("element", RefOr::Ref(Ref::new("#/test")))
2581 .build(),
2582 )))
2583 .build(),
2584 ))
2585 .item(Schema::Array(
2586 ArrayBuilder::new()
2587 .items(RefOr::T(Schema::Object(
2588 ObjectBuilder::new()
2589 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
2590 .build(),
2591 )))
2592 .build(),
2593 ))
2594 .build(),
2595 )),
2596 )
2597 .build(),
2598 ));
2599
2600 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2601 println!("----------------------------");
2602 println!("{json_str}");
2603
2604 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2605
2606 let json_de_str = serde_json::to_string(&deserialized).expect("");
2607 println!("----------------------------");
2608 println!("{json_de_str}");
2609
2610 assert_eq!(json_str, json_de_str);
2611 }
2612
2613 #[test]
2614 fn serialize_deserialize_all_of_of_within_ref_or_t_object_builder() {
2615 let ref_or_schema = RefOr::T(Schema::Object(
2616 ObjectBuilder::new()
2617 .property(
2618 "test",
2619 RefOr::T(Schema::AllOf(
2620 AllOfBuilder::new()
2621 .item(Schema::Array(
2622 ArrayBuilder::new()
2623 .items(RefOr::T(Schema::Object(
2624 ObjectBuilder::new()
2625 .property("element", RefOr::Ref(Ref::new("#/test")))
2626 .build(),
2627 )))
2628 .build(),
2629 ))
2630 .item(RefOr::T(Schema::Object(
2631 ObjectBuilder::new()
2632 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
2633 .build(),
2634 )))
2635 .build(),
2636 )),
2637 )
2638 .build(),
2639 ));
2640
2641 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2642 println!("----------------------------");
2643 println!("{json_str}");
2644
2645 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2646
2647 let json_de_str = serde_json::to_string(&deserialized).expect("");
2648 println!("----------------------------");
2649 println!("{json_de_str}");
2650
2651 assert_eq!(json_str, json_de_str);
2652 }
2653
2654 #[test]
2655 fn deserialize_reserialize_one_of_default_type() {
2656 let a = OneOfBuilder::new()
2657 .item(Schema::Array(
2658 ArrayBuilder::new()
2659 .items(RefOr::T(Schema::Object(
2660 ObjectBuilder::new()
2661 .property("element", RefOr::Ref(Ref::new("#/test")))
2662 .build(),
2663 )))
2664 .build(),
2665 ))
2666 .item(Schema::Array(
2667 ArrayBuilder::new()
2668 .items(RefOr::T(Schema::Object(
2669 ObjectBuilder::new()
2670 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
2671 .build(),
2672 )))
2673 .build(),
2674 ))
2675 .build();
2676
2677 let serialized_json = serde_json::to_string(&a).expect("should serialize to json");
2678 let b: OneOf = serde_json::from_str(&serialized_json).expect("should deserialize OneOf");
2679 let reserialized_json = serde_json::to_string(&b).expect("reserialized json");
2680
2681 println!("{serialized_json}");
2682 println!("{reserialized_json}",);
2683 assert_eq!(serialized_json, reserialized_json);
2684 }
2685
2686 #[test]
2687 fn serialize_deserialize_any_of_of_within_ref_or_t_object_builder() {
2688 let ref_or_schema = RefOr::T(Schema::Object(
2689 ObjectBuilder::new()
2690 .property(
2691 "test",
2692 RefOr::T(Schema::AnyOf(
2693 AnyOfBuilder::new()
2694 .item(Schema::Array(
2695 ArrayBuilder::new()
2696 .items(RefOr::T(Schema::Object(
2697 ObjectBuilder::new()
2698 .property("element", RefOr::Ref(Ref::new("#/test")))
2699 .build(),
2700 )))
2701 .build(),
2702 ))
2703 .item(RefOr::T(Schema::Object(
2704 ObjectBuilder::new()
2705 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
2706 .build(),
2707 )))
2708 .build(),
2709 )),
2710 )
2711 .build(),
2712 ));
2713
2714 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2715 println!("----------------------------");
2716 println!("{json_str}");
2717
2718 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2719
2720 let json_de_str = serde_json::to_string(&deserialized).expect("");
2721 println!("----------------------------");
2722 println!("{json_de_str}");
2723 assert!(json_str.contains("\"anyOf\""));
2724 assert_eq!(json_str, json_de_str);
2725 }
2726
2727 #[test]
2728 fn serialize_deserialize_schema_array_ref_or_t() {
2729 let ref_or_schema = RefOr::T(Schema::Array(
2730 ArrayBuilder::new()
2731 .items(RefOr::T(Schema::Object(
2732 ObjectBuilder::new()
2733 .property("element", RefOr::Ref(Ref::new("#/test")))
2734 .build(),
2735 )))
2736 .build(),
2737 ));
2738
2739 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2740 println!("----------------------------");
2741 println!("{json_str}");
2742
2743 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2744
2745 let json_de_str = serde_json::to_string(&deserialized).expect("");
2746 println!("----------------------------");
2747 println!("{json_de_str}");
2748
2749 assert_eq!(json_str, json_de_str);
2750 }
2751
2752 #[test]
2753 fn serialize_deserialize_schema_array_builder() {
2754 let ref_or_schema = ArrayBuilder::new()
2755 .items(RefOr::T(Schema::Object(
2756 ObjectBuilder::new()
2757 .property("element", RefOr::Ref(Ref::new("#/test")))
2758 .build(),
2759 )))
2760 .build();
2761
2762 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2763 println!("----------------------------");
2764 println!("{json_str}");
2765
2766 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2767
2768 let json_de_str = serde_json::to_string(&deserialized).expect("");
2769 println!("----------------------------");
2770 println!("{json_de_str}");
2771
2772 assert_eq!(json_str, json_de_str);
2773 }
2774
2775 #[test]
2776 fn serialize_deserialize_schema_with_additional_properties() {
2777 let schema = Schema::Object(
2778 ObjectBuilder::new()
2779 .property(
2780 "map",
2781 ObjectBuilder::new()
2782 .additional_properties(Some(AdditionalProperties::FreeForm(true))),
2783 )
2784 .build(),
2785 );
2786
2787 let json_str = serde_json::to_string(&schema).unwrap();
2788 println!("----------------------------");
2789 println!("{json_str}");
2790
2791 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
2792
2793 let json_de_str = serde_json::to_string(&deserialized).unwrap();
2794 println!("----------------------------");
2795 println!("{json_de_str}");
2796
2797 assert_eq!(json_str, json_de_str);
2798 }
2799
2800 #[test]
2801 fn serialize_deserialize_schema_with_additional_properties_object() {
2802 let schema = Schema::Object(
2803 ObjectBuilder::new()
2804 .property(
2805 "map",
2806 ObjectBuilder::new().additional_properties(Some(
2807 ObjectBuilder::new().property("name", Object::with_type(Type::String)),
2808 )),
2809 )
2810 .build(),
2811 );
2812
2813 let json_str = serde_json::to_string(&schema).unwrap();
2814 println!("----------------------------");
2815 println!("{json_str}");
2816
2817 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
2818
2819 let json_de_str = serde_json::to_string(&deserialized).unwrap();
2820 println!("----------------------------");
2821 println!("{json_de_str}");
2822
2823 assert_eq!(json_str, json_de_str);
2824 }
2825
2826 #[test]
2827 fn serialize_discriminator_with_mapping() {
2828 let mut discriminator = Discriminator::new("type");
2829 discriminator.mapping = [("int".to_string(), "#/components/schemas/MyInt".to_string())]
2830 .into_iter()
2831 .collect::<BTreeMap<_, _>>();
2832 let one_of = OneOfBuilder::new()
2833 .item(Ref::from_schema_name("MyInt"))
2834 .discriminator(Some(discriminator))
2835 .build();
2836 assert_json_snapshot!(one_of, @r##"
2837 {
2838 "oneOf": [
2839 {
2840 "$ref": "#/components/schemas/MyInt"
2841 }
2842 ],
2843 "discriminator": {
2844 "propertyName": "type",
2845 "mapping": {
2846 "int": "#/components/schemas/MyInt"
2847 }
2848 }
2849 }
2850 "##);
2851 }
2852
2853 #[test]
2854 fn serialize_deserialize_object_with_multiple_schema_types() {
2855 let object = ObjectBuilder::new()
2856 .schema_type(SchemaType::from_iter([Type::Object, Type::Null]))
2857 .build();
2858
2859 let json_str = serde_json::to_string(&object).unwrap();
2860 println!("----------------------------");
2861 println!("{json_str}");
2862
2863 let deserialized: Object = serde_json::from_str(&json_str).unwrap();
2864
2865 let json_de_str = serde_json::to_string(&deserialized).unwrap();
2866 println!("----------------------------");
2867 println!("{json_de_str}");
2868
2869 assert_eq!(json_str, json_de_str);
2870 }
2871
2872 #[test]
2873 fn object_with_extensions() {
2874 let expected = json!("value");
2875 let extensions = extensions::ExtensionsBuilder::new()
2876 .add("x-some-extension", expected.clone())
2877 .build();
2878 let json_value = ObjectBuilder::new().extensions(Some(extensions)).build();
2879
2880 let value = serde_json::to_value(&json_value).unwrap();
2881 assert_eq!(value.get("x-some-extension"), Some(&expected));
2882 }
2883
2884 #[test]
2885 fn array_with_extensions() {
2886 let expected = json!("value");
2887 let extensions = extensions::ExtensionsBuilder::new()
2888 .add("x-some-extension", expected.clone())
2889 .build();
2890 let json_value = ArrayBuilder::new().extensions(Some(extensions)).build();
2891
2892 let value = serde_json::to_value(&json_value).unwrap();
2893 assert_eq!(value.get("x-some-extension"), Some(&expected));
2894 }
2895
2896 #[test]
2897 fn oneof_with_extensions() {
2898 let expected = json!("value");
2899 let extensions = extensions::ExtensionsBuilder::new()
2900 .add("x-some-extension", expected.clone())
2901 .build();
2902 let json_value = OneOfBuilder::new().extensions(Some(extensions)).build();
2903
2904 let value = serde_json::to_value(&json_value).unwrap();
2905 assert_eq!(value.get("x-some-extension"), Some(&expected));
2906 }
2907
2908 #[test]
2909 fn allof_with_extensions() {
2910 let expected = json!("value");
2911 let extensions = extensions::ExtensionsBuilder::new()
2912 .add("x-some-extension", expected.clone())
2913 .build();
2914 let json_value = AllOfBuilder::new().extensions(Some(extensions)).build();
2915
2916 let value = serde_json::to_value(&json_value).unwrap();
2917 assert_eq!(value.get("x-some-extension"), Some(&expected));
2918 }
2919
2920 #[test]
2921 fn anyof_with_extensions() {
2922 let expected = json!("value");
2923 let extensions = extensions::ExtensionsBuilder::new()
2924 .add("x-some-extension", expected.clone())
2925 .build();
2926 let json_value = AnyOfBuilder::new().extensions(Some(extensions)).build();
2927
2928 let value = serde_json::to_value(&json_value).unwrap();
2929 assert_eq!(value.get("x-some-extension"), Some(&expected));
2930 }
2931}