1use std::collections::BTreeMap;
6
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9
10use super::extensions::Extensions;
11use super::RefOr;
12use super::{
13 builder,
14 example::Example,
15 header::Header,
16 link::Link,
17 path::{Callback, Parameter, PathItem},
18 request_body::RequestBody,
19 security::SecurityScheme,
20 set_value,
21 xml::Xml,
22 Content, Deprecated, Response,
23};
24use crate::{ToResponse, ToSchema};
25
26macro_rules! component_from_builder {
27 ( $name:ident ) => {
28 impl From<$name> for Schema {
29 fn from(builder: $name) -> Self {
30 builder.build().into()
31 }
32 }
33 };
34}
35
36macro_rules! to_array_builder {
37 () => {
38 pub fn to_array_builder(self) -> ArrayBuilder {
40 ArrayBuilder::from(Array::new(self))
41 }
42 };
43}
44
45pub fn empty() -> Schema {
50 Schema::Object(
51 ObjectBuilder::new()
52 .schema_type(SchemaType::AnyValue)
53 .default(Some(serde_json::Value::Null))
54 .into(),
55 )
56}
57
58builder! {
59 ComponentsBuilder;
60
61 #[non_exhaustive]
69 #[derive(Serialize, Deserialize, Default, Clone, PartialEq)]
70 #[cfg_attr(feature = "debug", derive(Debug))]
71 #[serde(rename_all = "camelCase")]
72 pub struct Components {
73 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
77 pub schemas: BTreeMap<String, RefOr<Schema>>,
78
79 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
85 pub responses: BTreeMap<String, RefOr<Response>>,
86
87 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
89 pub parameters: BTreeMap<String, RefOr<Parameter>>,
90
91 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
93 pub examples: BTreeMap<String, RefOr<Example>>,
94
95 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
97 pub request_bodies: BTreeMap<String, RefOr<RequestBody>>,
98
99 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
101 pub headers: BTreeMap<String, RefOr<Header>>,
102
103 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
105 pub links: BTreeMap<String, RefOr<Link>>,
106
107 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
109 pub callbacks: BTreeMap<String, RefOr<Callback>>,
110
111 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
113 pub path_items: BTreeMap<String, PathItem>,
114
115 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
119 pub media_types: BTreeMap<String, RefOr<Content>>,
120
121 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
125 pub security_schemes: BTreeMap<String, RefOr<SecurityScheme>>,
126
127 #[serde(skip_serializing_if = "Option::is_none", flatten)]
129 pub extensions: Option<Extensions>,
130 }
131}
132
133impl Components {
134 pub fn new() -> Self {
136 Self {
137 ..Default::default()
138 }
139 }
140 pub fn add_security_scheme<N: Into<String>, S: Into<RefOr<SecurityScheme>>>(
147 &mut self,
148 name: N,
149 security_scheme: S,
150 ) {
151 self.security_schemes
152 .insert(name.into(), security_scheme.into());
153 }
154
155 pub fn add_security_schemes_from_iter<
162 I: IntoIterator<Item = (N, S)>,
163 N: Into<String>,
164 S: Into<RefOr<SecurityScheme>>,
165 >(
166 &mut self,
167 schemas: I,
168 ) {
169 self.security_schemes.extend(
170 schemas
171 .into_iter()
172 .map(|(name, item)| (name.into(), item.into())),
173 );
174 }
175}
176
177impl ComponentsBuilder {
178 pub fn schema<S: Into<String>, I: Into<RefOr<Schema>>>(mut self, name: S, schema: I) -> Self {
182 self.schemas.insert(name.into(), schema.into());
183
184 self
185 }
186
187 pub fn schema_from<I: ToSchema>(mut self) -> Self {
204 let name = I::name();
205 let schema = I::schema();
206 self.schemas.insert(name.to_string(), schema);
207
208 self
209 }
210
211 pub fn schemas_from_iter<
230 I: IntoIterator<Item = (S, C)>,
231 C: Into<RefOr<Schema>>,
232 S: Into<String>,
233 >(
234 mut self,
235 schemas: I,
236 ) -> Self {
237 self.schemas.extend(
238 schemas
239 .into_iter()
240 .map(|(name, schema)| (name.into(), schema.into())),
241 );
242
243 self
244 }
245
246 pub fn response<S: Into<String>, R: Into<RefOr<Response>>>(
251 mut self,
252 name: S,
253 response: R,
254 ) -> Self {
255 self.responses.insert(name.into(), response.into());
256 self
257 }
258
259 pub fn response_from<'r, I: ToResponse<'r>>(self) -> Self {
265 let (name, response) = I::response();
266 self.response(name, response)
267 }
268
269 pub fn media_type<S: Into<String>, C: Into<RefOr<Content>>>(
290 mut self,
291 name: S,
292 media_type: C,
293 ) -> Self {
294 self.media_types.insert(name.into(), media_type.into());
295 self
296 }
297
298 pub fn media_types_from_iter<
316 I: IntoIterator<Item = (S, C)>,
317 S: Into<String>,
318 C: Into<RefOr<Content>>,
319 >(
320 mut self,
321 media_types: I,
322 ) -> Self {
323 self.media_types.extend(
324 media_types
325 .into_iter()
326 .map(|(name, media_type)| (name.into(), media_type.into())),
327 );
328
329 self
330 }
331
332 pub fn parameter<S: Into<String>, P: Into<RefOr<Parameter>>>(
350 mut self,
351 name: S,
352 parameter: P,
353 ) -> Self {
354 self.parameters.insert(name.into(), parameter.into());
355 self
356 }
357
358 pub fn example<S: Into<String>, E: Into<RefOr<Example>>>(
369 mut self,
370 name: S,
371 example: E,
372 ) -> Self {
373 self.examples.insert(name.into(), example.into());
374 self
375 }
376
377 pub fn request_body<S: Into<String>, R: Into<RefOr<RequestBody>>>(
398 mut self,
399 name: S,
400 request_body: R,
401 ) -> Self {
402 self.request_bodies.insert(name.into(), request_body.into());
403 self
404 }
405
406 pub fn header<S: Into<String>, H: Into<RefOr<Header>>>(mut self, name: S, header: H) -> Self {
422 self.headers.insert(name.into(), header.into());
423 self
424 }
425
426 pub fn link<S: Into<String>, L: Into<RefOr<Link>>>(mut self, name: S, link: L) -> Self {
437 self.links.insert(name.into(), link.into());
438 self
439 }
440
441 pub fn callback<S: Into<String>, C: Into<RefOr<Callback>>>(
464 mut self,
465 name: S,
466 callback: C,
467 ) -> Self {
468 self.callbacks.insert(name.into(), callback.into());
469 self
470 }
471
472 pub fn path_item<S: Into<String>, P: Into<PathItem>>(mut self, name: S, path_item: P) -> Self {
488 self.path_items.insert(name.into(), path_item.into());
489 self
490 }
491
492 pub fn responses_from_iter<
497 I: IntoIterator<Item = (S, R)>,
498 S: Into<String>,
499 R: Into<RefOr<Response>>,
500 >(
501 mut self,
502 responses: I,
503 ) -> Self {
504 self.responses.extend(
505 responses
506 .into_iter()
507 .map(|(name, response)| (name.into(), response.into())),
508 );
509
510 self
511 }
512
513 pub fn security_scheme<N: Into<String>, S: Into<RefOr<SecurityScheme>>>(
520 mut self,
521 name: N,
522 security_scheme: S,
523 ) -> Self {
524 self.security_schemes
525 .insert(name.into(), security_scheme.into());
526
527 self
528 }
529
530 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
532 set_value!(self extensions extensions)
533 }
534}
535
536#[non_exhaustive]
541#[derive(Serialize, Deserialize, Clone, PartialEq)]
542#[cfg_attr(feature = "debug", derive(Debug))]
543#[serde(untagged, rename_all = "camelCase")]
544pub enum Schema {
545 Array(Array),
548 Object(Object),
551 OneOf(OneOf),
557
558 AllOf(AllOf),
562
563 AnyOf(AnyOf),
567}
568
569impl Default for Schema {
570 fn default() -> Self {
571 Schema::Object(Object::default())
572 }
573}
574
575#[derive(Serialize, Deserialize, Clone, Default, PartialEq, Eq)]
580#[serde(rename_all = "camelCase")]
581#[cfg_attr(feature = "debug", derive(Debug))]
582pub struct Discriminator {
583 pub property_name: String,
586
587 #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
591 pub mapping: BTreeMap<String, String>,
592
593 #[serde(skip_serializing_if = "Option::is_none", flatten)]
595 pub extensions: Option<Extensions>,
596}
597
598impl Discriminator {
599 pub fn new<I: Into<String>>(property_name: I) -> Self {
609 Self {
610 property_name: property_name.into(),
611 mapping: BTreeMap::new(),
612 ..Default::default()
613 }
614 }
615
616 pub fn with_mapping<
633 P: Into<String>,
634 M: IntoIterator<Item = (K, V)>,
635 K: Into<String>,
636 V: Into<String>,
637 >(
638 property_name: P,
639 mapping: M,
640 ) -> Self {
641 Self {
642 property_name: property_name.into(),
643 mapping: BTreeMap::from_iter(
644 mapping
645 .into_iter()
646 .map(|(key, val)| (key.into(), val.into())),
647 ),
648 ..Default::default()
649 }
650 }
651}
652
653builder! {
654 OneOfBuilder;
655
656 #[derive(Serialize, Deserialize, Clone, PartialEq)]
663 #[cfg_attr(feature = "debug", derive(Debug))]
664 pub struct OneOf {
665 #[serde(rename = "oneOf")]
667 pub items: Vec<RefOr<Schema>>,
668
669 #[serde(rename = "type", default = "SchemaType::any", skip_serializing_if = "SchemaType::is_any_value")]
674 pub schema_type: SchemaType,
675
676 #[serde(skip_serializing_if = "Option::is_none")]
678 pub title: Option<String>,
679
680 #[serde(skip_serializing_if = "Option::is_none")]
682 pub description: Option<String>,
683
684 #[serde(skip_serializing_if = "Option::is_none")]
686 pub default: Option<Value>,
687
688 #[serde(skip_serializing_if = "Option::is_none")]
692 pub example: Option<Value>,
693
694 #[serde(skip_serializing_if = "Vec::is_empty", default)]
696 pub examples: Vec<Value>,
697
698 #[serde(skip_serializing_if = "Option::is_none")]
701 pub discriminator: Option<Discriminator>,
702
703 #[serde(skip_serializing_if = "Option::is_none", flatten)]
705 pub extensions: Option<Extensions>,
706
707 #[serde(rename = "readOnly", skip_serializing_if = "Option::is_none")]
709 pub read_only: Option<bool>,
710
711 #[serde(rename = "writeOnly", skip_serializing_if = "Option::is_none")]
713 pub write_only: Option<bool>,
714 }
715}
716
717impl OneOf {
718 pub fn new() -> Self {
720 Self {
721 ..Default::default()
722 }
723 }
724
725 pub fn with_capacity(capacity: usize) -> Self {
738 Self {
739 items: Vec::with_capacity(capacity),
740 ..Default::default()
741 }
742 }
743}
744
745impl Default for OneOf {
746 fn default() -> Self {
747 Self {
748 items: Default::default(),
749 schema_type: SchemaType::AnyValue,
750 title: Default::default(),
751 description: Default::default(),
752 default: Default::default(),
753 example: Default::default(),
754 examples: Default::default(),
755 discriminator: Default::default(),
756 extensions: Default::default(),
757 read_only: Default::default(),
758 write_only: Default::default(),
759 }
760 }
761}
762
763impl OneOfBuilder {
764 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
768 self.items.push(component.into());
769
770 self
771 }
772
773 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
776 set_value!(self schema_type schema_type.into())
777 }
778
779 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
781 set_value!(self title title.map(|title| title.into()))
782 }
783
784 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
786 set_value!(self description description.map(|description| description.into()))
787 }
788
789 pub fn default(mut self, default: Option<Value>) -> Self {
791 set_value!(self default default)
792 }
793
794 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
798 pub fn example(mut self, example: Option<Value>) -> Self {
799 set_value!(self example example)
800 }
801
802 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
804 set_value!(self examples examples.into_iter().map(Into::into).collect())
805 }
806
807 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
809 set_value!(self discriminator discriminator)
810 }
811
812 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
814 set_value!(self extensions extensions)
815 }
816
817 pub fn read_only(mut self, read_only: bool) -> Self {
819 set_value!(self read_only Some(read_only))
820 }
821
822 pub fn write_only(mut self, write_only: bool) -> Self {
824 set_value!(self write_only Some(write_only))
825 }
826
827 to_array_builder!();
828}
829
830impl From<OneOf> for Schema {
831 fn from(one_of: OneOf) -> Self {
832 Self::OneOf(one_of)
833 }
834}
835
836impl From<OneOfBuilder> for RefOr<Schema> {
837 fn from(one_of: OneOfBuilder) -> Self {
838 Self::T(Schema::OneOf(one_of.build()))
839 }
840}
841
842impl From<OneOfBuilder> for ArrayItems {
843 fn from(value: OneOfBuilder) -> Self {
844 Self::RefOrSchema(Box::new(value.into()))
845 }
846}
847
848component_from_builder!(OneOfBuilder);
849
850builder! {
851 AllOfBuilder;
852
853 #[derive(Serialize, Deserialize, Clone, PartialEq)]
860 #[cfg_attr(feature = "debug", derive(Debug))]
861 pub struct AllOf {
862 #[serde(rename = "allOf")]
864 pub items: Vec<RefOr<Schema>>,
865
866 #[serde(rename = "type", default = "SchemaType::any", skip_serializing_if = "SchemaType::is_any_value")]
871 pub schema_type: SchemaType,
872
873 #[serde(skip_serializing_if = "Option::is_none")]
875 pub title: Option<String>,
876
877 #[serde(skip_serializing_if = "Option::is_none")]
879 pub description: Option<String>,
880
881 #[serde(skip_serializing_if = "Option::is_none")]
883 pub default: Option<Value>,
884
885 #[serde(skip_serializing_if = "Option::is_none")]
889 pub example: Option<Value>,
890
891 #[serde(skip_serializing_if = "Vec::is_empty", default)]
893 pub examples: Vec<Value>,
894
895 #[serde(skip_serializing_if = "Option::is_none")]
898 pub discriminator: Option<Discriminator>,
899
900 #[serde(skip_serializing_if = "Option::is_none", flatten)]
902 pub extensions: Option<Extensions>,
903 }
904}
905
906impl AllOf {
907 pub fn new() -> Self {
909 Self {
910 ..Default::default()
911 }
912 }
913
914 pub fn with_capacity(capacity: usize) -> Self {
927 Self {
928 items: Vec::with_capacity(capacity),
929 ..Default::default()
930 }
931 }
932}
933
934impl Default for AllOf {
935 fn default() -> Self {
936 Self {
937 items: Default::default(),
938 schema_type: SchemaType::AnyValue,
939 title: Default::default(),
940 description: Default::default(),
941 default: Default::default(),
942 example: Default::default(),
943 examples: Default::default(),
944 discriminator: Default::default(),
945 extensions: Default::default(),
946 }
947 }
948}
949
950impl AllOfBuilder {
951 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
955 self.items.push(component.into());
956
957 self
958 }
959
960 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
963 set_value!(self schema_type schema_type.into())
964 }
965
966 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
968 set_value!(self title title.map(|title| title.into()))
969 }
970
971 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
973 set_value!(self description description.map(|description| description.into()))
974 }
975
976 pub fn default(mut self, default: Option<Value>) -> Self {
978 set_value!(self default default)
979 }
980
981 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
985 pub fn example(mut self, example: Option<Value>) -> Self {
986 set_value!(self example example)
987 }
988
989 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
991 set_value!(self examples examples.into_iter().map(Into::into).collect())
992 }
993
994 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
996 set_value!(self discriminator discriminator)
997 }
998
999 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
1001 set_value!(self extensions extensions)
1002 }
1003
1004 to_array_builder!();
1005}
1006
1007impl From<AllOf> for Schema {
1008 fn from(one_of: AllOf) -> Self {
1009 Self::AllOf(one_of)
1010 }
1011}
1012
1013impl From<AllOfBuilder> for RefOr<Schema> {
1014 fn from(one_of: AllOfBuilder) -> Self {
1015 Self::T(Schema::AllOf(one_of.build()))
1016 }
1017}
1018
1019impl From<AllOfBuilder> for ArrayItems {
1020 fn from(value: AllOfBuilder) -> Self {
1021 Self::RefOrSchema(Box::new(value.into()))
1022 }
1023}
1024
1025component_from_builder!(AllOfBuilder);
1026
1027builder! {
1028 AnyOfBuilder;
1029
1030 #[derive(Serialize, Deserialize, Clone, PartialEq)]
1037 #[cfg_attr(feature = "debug", derive(Debug))]
1038 pub struct AnyOf {
1039 #[serde(rename = "anyOf")]
1041 pub items: Vec<RefOr<Schema>>,
1042
1043 #[serde(rename = "type", default = "SchemaType::any", skip_serializing_if = "SchemaType::is_any_value")]
1048 pub schema_type: SchemaType,
1049
1050 #[serde(skip_serializing_if = "Option::is_none")]
1052 pub description: Option<String>,
1053
1054 #[serde(skip_serializing_if = "Option::is_none")]
1056 pub default: Option<Value>,
1057
1058 #[serde(skip_serializing_if = "Option::is_none")]
1062 pub example: Option<Value>,
1063
1064 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1066 pub examples: Vec<Value>,
1067
1068 #[serde(skip_serializing_if = "Option::is_none")]
1071 pub discriminator: Option<Discriminator>,
1072
1073 #[serde(skip_serializing_if = "Option::is_none", flatten)]
1075 pub extensions: Option<Extensions>,
1076 }
1077}
1078
1079impl AnyOf {
1080 pub fn new() -> Self {
1082 Self {
1083 ..Default::default()
1084 }
1085 }
1086
1087 pub fn with_capacity(capacity: usize) -> Self {
1100 Self {
1101 items: Vec::with_capacity(capacity),
1102 ..Default::default()
1103 }
1104 }
1105}
1106
1107impl Default for AnyOf {
1108 fn default() -> Self {
1109 Self {
1110 items: Default::default(),
1111 schema_type: SchemaType::AnyValue,
1112 description: Default::default(),
1113 default: Default::default(),
1114 example: Default::default(),
1115 examples: Default::default(),
1116 discriminator: Default::default(),
1117 extensions: Default::default(),
1118 }
1119 }
1120}
1121
1122impl AnyOfBuilder {
1123 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
1127 self.items.push(component.into());
1128
1129 self
1130 }
1131
1132 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
1135 set_value!(self schema_type schema_type.into())
1136 }
1137
1138 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
1140 set_value!(self description description.map(|description| description.into()))
1141 }
1142
1143 pub fn default(mut self, default: Option<Value>) -> Self {
1145 set_value!(self default default)
1146 }
1147
1148 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
1152 pub fn example(mut self, example: Option<Value>) -> Self {
1153 set_value!(self example example)
1154 }
1155
1156 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
1158 set_value!(self examples examples.into_iter().map(Into::into).collect())
1159 }
1160
1161 pub fn discriminator(mut self, discriminator: Option<Discriminator>) -> Self {
1163 set_value!(self discriminator discriminator)
1164 }
1165
1166 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
1168 set_value!(self extensions extensions)
1169 }
1170
1171 to_array_builder!();
1172}
1173
1174impl From<AnyOf> for Schema {
1175 fn from(any_of: AnyOf) -> Self {
1176 Self::AnyOf(any_of)
1177 }
1178}
1179
1180impl From<AnyOfBuilder> for RefOr<Schema> {
1181 fn from(any_of: AnyOfBuilder) -> Self {
1182 Self::T(Schema::AnyOf(any_of.build()))
1183 }
1184}
1185
1186impl From<AnyOfBuilder> for ArrayItems {
1187 fn from(value: AnyOfBuilder) -> Self {
1188 Self::RefOrSchema(Box::new(value.into()))
1189 }
1190}
1191
1192component_from_builder!(AnyOfBuilder);
1193
1194#[cfg(not(feature = "preserve_order"))]
1195type ObjectPropertiesMap<K, V> = BTreeMap<K, V>;
1196#[cfg(feature = "preserve_order")]
1197type ObjectPropertiesMap<K, V> = indexmap::IndexMap<K, V>;
1198
1199builder! {
1200 ObjectBuilder;
1201
1202 #[non_exhaustive]
1209 #[derive(Serialize, Deserialize, Default, Clone, PartialEq)]
1210 #[cfg_attr(feature = "debug", derive(Debug))]
1211 #[serde(rename_all = "camelCase")]
1212 pub struct Object {
1213 #[serde(rename = "type", skip_serializing_if="SchemaType::is_any_value")]
1216 pub schema_type: SchemaType,
1217
1218 #[serde(skip_serializing_if = "Option::is_none")]
1220 pub title: Option<String>,
1221
1222 #[serde(skip_serializing_if = "Option::is_none")]
1224 pub format: Option<SchemaFormat>,
1225
1226 #[serde(skip_serializing_if = "Option::is_none")]
1228 pub description: Option<String>,
1229
1230 #[serde(skip_serializing_if = "Option::is_none")]
1232 pub default: Option<Value>,
1233
1234 #[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
1236 pub enum_values: Option<Vec<Value>>,
1237
1238 #[serde(skip_serializing_if = "Vec::is_empty", default = "Vec::new")]
1240 pub required: Vec<String>,
1241
1242 #[serde(skip_serializing_if = "ObjectPropertiesMap::is_empty", default = "ObjectPropertiesMap::new")]
1250 pub properties: ObjectPropertiesMap<String, RefOr<Schema>>,
1251
1252 #[serde(skip_serializing_if = "Option::is_none")]
1254 pub additional_properties: Option<Box<AdditionalProperties<Schema>>>,
1255
1256 #[serde(skip_serializing_if = "Option::is_none")]
1259 pub property_names: Option<Box<Schema>>,
1260
1261 #[serde(skip_serializing_if = "Option::is_none")]
1263 pub deprecated: Option<Deprecated>,
1264
1265 #[serde(skip_serializing_if = "Option::is_none")]
1269 pub example: Option<Value>,
1270
1271 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1273 pub examples: Vec<Value>,
1274
1275 #[serde(skip_serializing_if = "Option::is_none")]
1277 pub write_only: Option<bool>,
1278
1279 #[serde(skip_serializing_if = "Option::is_none")]
1281 pub read_only: Option<bool>,
1282
1283 #[serde(skip_serializing_if = "Option::is_none")]
1285 pub xml: Option<Xml>,
1286
1287 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1290 pub multiple_of: Option<crate::utoipa::Number>,
1291
1292 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1295 pub maximum: Option<crate::utoipa::Number>,
1296
1297 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1300 pub minimum: Option<crate::utoipa::Number>,
1301
1302 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1305 pub exclusive_maximum: Option<crate::utoipa::Number>,
1306
1307 #[serde(skip_serializing_if = "Option::is_none", serialize_with = "omit_decimal_zero")]
1310 pub exclusive_minimum: Option<crate::utoipa::Number>,
1311
1312 #[serde(skip_serializing_if = "Option::is_none")]
1315 pub max_length: Option<usize>,
1316
1317 #[serde(skip_serializing_if = "Option::is_none")]
1321 pub min_length: Option<usize>,
1322
1323 #[serde(skip_serializing_if = "Option::is_none")]
1326 pub pattern: Option<String>,
1327
1328 #[serde(skip_serializing_if = "Option::is_none")]
1330 pub max_properties: Option<usize>,
1331
1332 #[serde(skip_serializing_if = "Option::is_none")]
1335 pub min_properties: Option<usize>,
1336
1337 #[serde(skip_serializing_if = "Option::is_none", flatten)]
1339 pub extensions: Option<Extensions>,
1340
1341 #[serde(skip_serializing_if = "String::is_empty", default)]
1350 pub content_encoding: String,
1351
1352 #[serde(skip_serializing_if = "String::is_empty", default)]
1357 pub content_media_type: String,
1358
1359 #[serde(skip_serializing_if = "Option::is_none")]
1361 pub content_schema: Option<Box<RefOr<Schema>>>,
1362 }
1363}
1364
1365fn is_false(value: &bool) -> bool {
1366 !*value
1367}
1368
1369impl Object {
1370 pub fn new() -> Self {
1373 Self {
1374 ..Default::default()
1375 }
1376 }
1377
1378 pub fn with_type<T: Into<SchemaType>>(schema_type: T) -> Self {
1386 Self {
1387 schema_type: schema_type.into(),
1388 ..Default::default()
1389 }
1390 }
1391}
1392
1393impl From<Object> for Schema {
1394 fn from(s: Object) -> Self {
1395 Self::Object(s)
1396 }
1397}
1398
1399impl From<Object> for ArrayItems {
1400 fn from(value: Object) -> Self {
1401 Self::RefOrSchema(Box::new(value.into()))
1402 }
1403}
1404
1405impl ToArray for Object {}
1406
1407impl ObjectBuilder {
1408 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
1411 set_value!(self schema_type schema_type.into())
1412 }
1413
1414 pub fn format(mut self, format: Option<SchemaFormat>) -> Self {
1416 set_value!(self format format)
1417 }
1418
1419 pub fn property<S: Into<String>, I: Into<RefOr<Schema>>>(
1423 mut self,
1424 property_name: S,
1425 component: I,
1426 ) -> Self {
1427 self.properties
1428 .insert(property_name.into(), component.into());
1429
1430 self
1431 }
1432
1433 pub fn additional_properties<I: Into<AdditionalProperties<Schema>>>(
1435 mut self,
1436 additional_properties: Option<I>,
1437 ) -> Self {
1438 set_value!(self additional_properties additional_properties.map(|additional_properties| Box::new(additional_properties.into())))
1439 }
1440
1441 pub fn property_names<S: Into<Schema>>(mut self, property_name: Option<S>) -> Self {
1444 set_value!(self property_names property_name.map(|property_name| Box::new(property_name.into())))
1445 }
1446
1447 pub fn required<I: Into<String>>(mut self, required_field: I) -> Self {
1449 self.required.push(required_field.into());
1450
1451 self
1452 }
1453
1454 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
1456 set_value!(self title title.map(|title| title.into()))
1457 }
1458
1459 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
1461 set_value!(self description description.map(|description| description.into()))
1462 }
1463
1464 pub fn default(mut self, default: Option<Value>) -> Self {
1466 set_value!(self default default)
1467 }
1468
1469 pub fn deprecated(mut self, deprecated: Option<Deprecated>) -> Self {
1471 set_value!(self deprecated deprecated)
1472 }
1473
1474 pub fn enum_values<I: IntoIterator<Item = E>, E: Into<Value>>(
1476 mut self,
1477 enum_values: Option<I>,
1478 ) -> Self {
1479 set_value!(self enum_values
1480 enum_values.map(|values| values.into_iter().map(|enum_value| enum_value.into()).collect()))
1481 }
1482
1483 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
1487 pub fn example(mut self, example: Option<Value>) -> Self {
1488 set_value!(self example example)
1489 }
1490
1491 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
1493 set_value!(self examples examples.into_iter().map(Into::into).collect())
1494 }
1495
1496 pub fn write_only(mut self, write_only: bool) -> Self {
1498 set_value!(self write_only Some(write_only))
1499 }
1500
1501 pub fn read_only(mut self, read_only: bool) -> Self {
1503 set_value!(self read_only Some(read_only))
1504 }
1505
1506 pub fn xml(mut self, xml: Option<Xml>) -> Self {
1508 set_value!(self xml xml)
1509 }
1510
1511 pub fn multiple_of<N: Into<crate::utoipa::Number>>(mut self, multiple_of: Option<N>) -> Self {
1513 set_value!(self multiple_of multiple_of.map(|multiple_of| multiple_of.into()))
1514 }
1515
1516 pub fn maximum<N: Into<crate::utoipa::Number>>(mut self, maximum: Option<N>) -> Self {
1518 set_value!(self maximum maximum.map(|max| max.into()))
1519 }
1520
1521 pub fn minimum<N: Into<crate::utoipa::Number>>(mut self, minimum: Option<N>) -> Self {
1523 set_value!(self minimum minimum.map(|min| min.into()))
1524 }
1525
1526 pub fn exclusive_maximum<N: Into<crate::utoipa::Number>>(
1528 mut self,
1529 exclusive_maximum: Option<N>,
1530 ) -> Self {
1531 set_value!(self exclusive_maximum exclusive_maximum.map(|exclusive_maximum| exclusive_maximum.into()))
1532 }
1533
1534 pub fn exclusive_minimum<N: Into<crate::utoipa::Number>>(
1536 mut self,
1537 exclusive_minimum: Option<N>,
1538 ) -> Self {
1539 set_value!(self exclusive_minimum exclusive_minimum.map(|exclusive_minimum| exclusive_minimum.into()))
1540 }
1541
1542 pub fn max_length(mut self, max_length: Option<usize>) -> Self {
1544 set_value!(self max_length max_length)
1545 }
1546
1547 pub fn min_length(mut self, min_length: Option<usize>) -> Self {
1549 set_value!(self min_length min_length)
1550 }
1551
1552 pub fn pattern<I: Into<String>>(mut self, pattern: Option<I>) -> Self {
1554 set_value!(self pattern pattern.map(|pattern| pattern.into()))
1555 }
1556
1557 pub fn max_properties(mut self, max_properties: Option<usize>) -> Self {
1559 set_value!(self max_properties max_properties)
1560 }
1561
1562 pub fn min_properties(mut self, min_properties: Option<usize>) -> Self {
1564 set_value!(self min_properties min_properties)
1565 }
1566
1567 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
1569 set_value!(self extensions extensions)
1570 }
1571
1572 pub fn content_encoding<S: Into<String>>(mut self, content_encoding: S) -> Self {
1575 set_value!(self content_encoding content_encoding.into())
1576 }
1577
1578 pub fn content_media_type<S: Into<String>>(mut self, content_media_type: S) -> Self {
1581 set_value!(self content_media_type content_media_type.into())
1582 }
1583
1584 pub fn content_schema<I: Into<RefOr<Schema>>>(mut self, content_schema: Option<I>) -> Self {
1586 set_value!(self content_schema content_schema.map(|schema| Box::new(schema.into())))
1587 }
1588
1589 to_array_builder!();
1590}
1591
1592component_from_builder!(ObjectBuilder);
1593
1594impl From<ObjectBuilder> for RefOr<Schema> {
1595 fn from(builder: ObjectBuilder) -> Self {
1596 Self::T(Schema::Object(builder.build()))
1597 }
1598}
1599
1600impl From<RefOr<Schema>> for Schema {
1601 fn from(value: RefOr<Schema>) -> Self {
1602 match value {
1603 RefOr::Ref(_) => {
1604 panic!("Invalid type `RefOr::Ref` provided, cannot convert to RefOr::T<Schema>")
1605 }
1606 RefOr::T(value) => value,
1607 }
1608 }
1609}
1610
1611impl From<ObjectBuilder> for ArrayItems {
1612 fn from(value: ObjectBuilder) -> Self {
1613 Self::RefOrSchema(Box::new(value.into()))
1614 }
1615}
1616
1617#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
1621#[cfg_attr(feature = "debug", derive(Debug))]
1622#[serde(untagged)]
1623pub enum AdditionalProperties<T> {
1624 RefOr(RefOr<T>),
1626 FreeForm(bool),
1628}
1629
1630impl<T> From<RefOr<T>> for AdditionalProperties<T> {
1631 fn from(value: RefOr<T>) -> Self {
1632 Self::RefOr(value)
1633 }
1634}
1635
1636impl From<ObjectBuilder> for AdditionalProperties<Schema> {
1637 fn from(value: ObjectBuilder) -> Self {
1638 Self::RefOr(RefOr::T(Schema::Object(value.build())))
1639 }
1640}
1641
1642impl From<ArrayBuilder> for AdditionalProperties<Schema> {
1643 fn from(value: ArrayBuilder) -> Self {
1644 Self::RefOr(RefOr::T(Schema::Array(value.build())))
1645 }
1646}
1647
1648impl From<Ref> for AdditionalProperties<Schema> {
1649 fn from(value: Ref) -> Self {
1650 Self::RefOr(RefOr::Ref(value))
1651 }
1652}
1653
1654impl From<RefBuilder> for AdditionalProperties<Schema> {
1655 fn from(value: RefBuilder) -> Self {
1656 Self::RefOr(RefOr::Ref(value.build()))
1657 }
1658}
1659
1660impl From<Schema> for AdditionalProperties<Schema> {
1661 fn from(value: Schema) -> Self {
1662 Self::RefOr(RefOr::T(value))
1663 }
1664}
1665
1666impl From<AllOfBuilder> for AdditionalProperties<Schema> {
1667 fn from(value: AllOfBuilder) -> Self {
1668 Self::RefOr(RefOr::T(Schema::AllOf(value.build())))
1669 }
1670}
1671
1672builder! {
1673 RefBuilder;
1674
1675 #[non_exhaustive]
1680 #[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq)]
1681 #[cfg_attr(feature = "debug", derive(Debug))]
1682 pub struct Ref {
1683 #[serde(rename = "$ref")]
1685 pub ref_location: String,
1686
1687 #[serde(skip_serializing_if = "String::is_empty", default)]
1691 pub description: String,
1692
1693 #[serde(skip_serializing_if = "String::is_empty", default)]
1696 pub summary: String,
1697
1698 #[serde(rename = "readOnly", skip_serializing_if = "Option::is_none")]
1703 pub read_only: Option<bool>,
1704
1705 #[serde(rename = "writeOnly", skip_serializing_if = "Option::is_none")]
1710 pub write_only: Option<bool>,
1711
1712 #[serde(skip_serializing_if = "Option::is_none")]
1714 pub default: Option<Value>,
1715
1716 #[serde(skip_serializing_if = "Option::is_none")]
1718 pub title: Option<String>,
1719 }
1720}
1721
1722impl Ref {
1723 pub fn new<I: Into<String>>(ref_location: I) -> Self {
1726 Self {
1727 ref_location: ref_location.into(),
1728 ..Default::default()
1729 }
1730 }
1731
1732 pub fn from_schema_name<I: Into<String>>(schema_name: I) -> Self {
1735 Self::new(format!("#/components/schemas/{}", schema_name.into()))
1736 }
1737
1738 pub fn from_response_name<I: Into<String>>(response_name: I) -> Self {
1741 Self::new(format!("#/components/responses/{}", response_name.into()))
1742 }
1743
1744 to_array_builder!();
1745}
1746
1747impl RefBuilder {
1748 pub fn ref_location(mut self, ref_location: String) -> Self {
1750 set_value!(self ref_location ref_location)
1751 }
1752
1753 pub fn ref_location_from_schema_name<S: Into<String>>(mut self, schema_name: S) -> Self {
1756 set_value!(self ref_location format!("#/components/schemas/{}", schema_name.into()))
1757 }
1758
1759 pub fn description<S: Into<String>>(mut self, description: Option<S>) -> Self {
1765 set_value!(self description description.map(Into::into).unwrap_or_default())
1766 }
1767
1768 pub fn summary<S: Into<String>>(mut self, summary: S) -> Self {
1771 set_value!(self summary summary.into())
1772 }
1773
1774 pub fn read_only(mut self, read_only: bool) -> Self {
1776 set_value!(self read_only Some(read_only))
1777 }
1778
1779 pub fn write_only(mut self, write_only: bool) -> Self {
1781 set_value!(self write_only Some(write_only))
1782 }
1783
1784 pub fn default(mut self, default: Option<Value>) -> Self {
1786 set_value!(self default default)
1787 }
1788
1789 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
1791 set_value!(self title title.map(|title| title.into()))
1792 }
1793}
1794
1795impl From<RefBuilder> for RefOr<Schema> {
1796 fn from(builder: RefBuilder) -> Self {
1797 Self::Ref(builder.build())
1798 }
1799}
1800
1801impl From<RefBuilder> for ArrayItems {
1802 fn from(value: RefBuilder) -> Self {
1803 Self::RefOrSchema(Box::new(value.into()))
1804 }
1805}
1806
1807impl From<Ref> for RefOr<Schema> {
1808 fn from(r: Ref) -> Self {
1809 Self::Ref(r)
1810 }
1811}
1812
1813impl From<Ref> for ArrayItems {
1814 fn from(value: Ref) -> Self {
1815 Self::RefOrSchema(Box::new(value.into()))
1816 }
1817}
1818
1819impl<T> From<T> for RefOr<T> {
1820 fn from(t: T) -> Self {
1821 Self::T(t)
1822 }
1823}
1824
1825impl Default for RefOr<Schema> {
1826 fn default() -> Self {
1827 Self::T(Schema::Object(Object::new()))
1828 }
1829}
1830
1831impl ToArray for RefOr<Schema> {}
1832
1833impl From<Object> for RefOr<Schema> {
1834 fn from(object: Object) -> Self {
1835 Self::T(Schema::Object(object))
1836 }
1837}
1838
1839impl From<Array> for RefOr<Schema> {
1840 fn from(array: Array) -> Self {
1841 Self::T(Schema::Array(array))
1842 }
1843}
1844
1845fn omit_decimal_zero<S>(
1846 maybe_value: &Option<crate::utoipa::Number>,
1847 serializer: S,
1848) -> Result<S::Ok, S::Error>
1849where
1850 S: serde::Serializer,
1851{
1852 match maybe_value {
1853 Some(crate::utoipa::Number::Float(float)) => {
1854 if float.fract() == 0.0 && *float >= i64::MIN as f64 && *float <= i64::MAX as f64 {
1855 serializer.serialize_i64(float.trunc() as i64)
1856 } else {
1857 serializer.serialize_f64(*float)
1858 }
1859 }
1860 Some(crate::utoipa::Number::Int(int)) => serializer.serialize_i64(*int as i64),
1861 Some(crate::utoipa::Number::UInt(uint)) => serializer.serialize_u64(*uint as u64),
1862 None => serializer.serialize_none(),
1863 }
1864}
1865
1866#[derive(Serialize, Deserialize, Clone, PartialEq)]
1870#[cfg_attr(feature = "debug", derive(Debug))]
1871#[serde(untagged)]
1872pub enum ArrayItems {
1873 RefOrSchema(Box<RefOr<Schema>>),
1875 #[serde(with = "array_items_false")]
1881 False,
1882}
1883
1884mod array_items_false {
1885 use serde::de::Visitor;
1886
1887 pub fn serialize<S: serde::Serializer>(serializer: S) -> Result<S::Ok, S::Error> {
1888 serializer.serialize_bool(false)
1889 }
1890
1891 pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<(), D::Error> {
1892 struct ItemsFalseVisitor;
1893
1894 impl<'de> Visitor<'de> for ItemsFalseVisitor {
1895 type Value = ();
1896 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
1897 where
1898 E: serde::de::Error,
1899 {
1900 if !v {
1901 Ok(())
1902 } else {
1903 Err(serde::de::Error::custom(format!(
1904 "invalid boolean value: {v}, expected false"
1905 )))
1906 }
1907 }
1908
1909 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
1910 formatter.write_str("expected boolean false")
1911 }
1912 }
1913
1914 deserializer.deserialize_bool(ItemsFalseVisitor)
1915 }
1916}
1917
1918impl Default for ArrayItems {
1919 fn default() -> Self {
1920 Self::RefOrSchema(Box::new(Object::with_type(SchemaType::AnyValue).into()))
1921 }
1922}
1923
1924impl From<RefOr<Schema>> for ArrayItems {
1925 fn from(value: RefOr<Schema>) -> Self {
1926 Self::RefOrSchema(Box::new(value))
1927 }
1928}
1929
1930builder! {
1931 ArrayBuilder;
1932
1933 #[non_exhaustive]
1937 #[derive(Serialize, Deserialize, Clone, PartialEq)]
1938 #[cfg_attr(feature = "debug", derive(Debug))]
1939 #[serde(rename_all = "camelCase")]
1940 pub struct Array {
1941 #[serde(rename = "type")]
1943 pub schema_type: SchemaType,
1944
1945 #[serde(skip_serializing_if = "Option::is_none")]
1947 pub title: Option<String>,
1948
1949 pub items: ArrayItems,
1951
1952 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1957 pub prefix_items: Vec<Schema>,
1958
1959 #[serde(skip_serializing_if = "Option::is_none")]
1961 pub description: Option<String>,
1962
1963 #[serde(skip_serializing_if = "Option::is_none")]
1965 pub deprecated: Option<Deprecated>,
1966
1967 #[serde(skip_serializing_if = "Option::is_none")]
1971 pub example: Option<Value>,
1972
1973 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1975 pub examples: Vec<Value>,
1976
1977 #[serde(skip_serializing_if = "Option::is_none")]
1979 pub default: Option<Value>,
1980
1981 #[serde(skip_serializing_if = "Option::is_none")]
1983 pub max_items: Option<usize>,
1984
1985 #[serde(skip_serializing_if = "Option::is_none")]
1987 pub min_items: Option<usize>,
1988
1989 #[serde(default, skip_serializing_if = "is_false")]
1992 pub unique_items: bool,
1993
1994 #[serde(skip_serializing_if = "Option::is_none")]
1996 pub xml: Option<Xml>,
1997
1998 #[serde(skip_serializing_if = "String::is_empty", default)]
2007 pub content_encoding: String,
2008
2009 #[serde(skip_serializing_if = "String::is_empty", default)]
2014 pub content_media_type: String,
2015
2016 #[serde(skip_serializing_if = "Option::is_none")]
2018 pub content_schema: Option<Box<RefOr<Schema>>>,
2019
2020 #[serde(skip_serializing_if = "Option::is_none", flatten)]
2022 pub extensions: Option<Extensions>,
2023 }
2024}
2025
2026impl Default for Array {
2027 fn default() -> Self {
2028 Self {
2029 title: Default::default(),
2030 schema_type: Type::Array.into(),
2031 unique_items: bool::default(),
2032 items: Default::default(),
2033 prefix_items: Vec::default(),
2034 description: Default::default(),
2035 deprecated: Default::default(),
2036 example: Default::default(),
2037 examples: Default::default(),
2038 default: Default::default(),
2039 max_items: Default::default(),
2040 min_items: Default::default(),
2041 xml: Default::default(),
2042 extensions: Default::default(),
2043 content_encoding: Default::default(),
2044 content_media_type: Default::default(),
2045 content_schema: Default::default(),
2046 }
2047 }
2048}
2049
2050impl Array {
2051 pub fn new<I: Into<RefOr<Schema>>>(component: I) -> Self {
2061 Self {
2062 items: ArrayItems::RefOrSchema(Box::new(component.into())),
2063 ..Default::default()
2064 }
2065 }
2066
2067 pub fn new_nullable<I: Into<RefOr<Schema>>>(component: I) -> Self {
2077 Self {
2078 items: ArrayItems::RefOrSchema(Box::new(component.into())),
2079 schema_type: SchemaType::from_iter([Type::Array, Type::Null]),
2080 ..Default::default()
2081 }
2082 }
2083}
2084
2085impl ArrayBuilder {
2086 pub fn items<I: Into<ArrayItems>>(mut self, items: I) -> Self {
2088 set_value!(self items items.into())
2089 }
2090
2091 pub fn prefix_items<I: IntoIterator<Item = S>, S: Into<Schema>>(mut self, items: I) -> Self {
2096 self.prefix_items = items
2097 .into_iter()
2098 .map(|item| item.into())
2099 .collect::<Vec<_>>();
2100
2101 self
2102 }
2103
2104 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
2118 set_value!(self schema_type schema_type.into())
2119 }
2120
2121 pub fn title<I: Into<String>>(mut self, title: Option<I>) -> Self {
2123 set_value!(self title title.map(|title| title.into()))
2124 }
2125
2126 pub fn description<I: Into<String>>(mut self, description: Option<I>) -> Self {
2128 set_value!(self description description.map(|description| description.into()))
2129 }
2130
2131 pub fn deprecated(mut self, deprecated: Option<Deprecated>) -> Self {
2133 set_value!(self deprecated deprecated)
2134 }
2135
2136 #[deprecated = "Since OpenAPI 3.1 prefer using `examples`"]
2140 pub fn example(mut self, example: Option<Value>) -> Self {
2141 set_value!(self example example)
2142 }
2143
2144 pub fn examples<I: IntoIterator<Item = V>, V: Into<Value>>(mut self, examples: I) -> Self {
2146 set_value!(self examples examples.into_iter().map(Into::into).collect())
2147 }
2148
2149 pub fn default(mut self, default: Option<Value>) -> Self {
2151 set_value!(self default default)
2152 }
2153
2154 pub fn max_items(mut self, max_items: Option<usize>) -> Self {
2156 set_value!(self max_items max_items)
2157 }
2158
2159 pub fn min_items(mut self, min_items: Option<usize>) -> Self {
2161 set_value!(self min_items min_items)
2162 }
2163
2164 pub fn unique_items(mut self, unique_items: bool) -> Self {
2166 set_value!(self unique_items unique_items)
2167 }
2168
2169 pub fn xml(mut self, xml: Option<Xml>) -> Self {
2171 set_value!(self xml xml)
2172 }
2173
2174 pub fn content_encoding<S: Into<String>>(mut self, content_encoding: S) -> Self {
2177 set_value!(self content_encoding content_encoding.into())
2178 }
2179
2180 pub fn content_media_type<S: Into<String>>(mut self, content_media_type: S) -> Self {
2183 set_value!(self content_media_type content_media_type.into())
2184 }
2185
2186 pub fn content_schema<I: Into<RefOr<Schema>>>(mut self, content_schema: Option<I>) -> Self {
2188 set_value!(self content_schema content_schema.map(|schema| Box::new(schema.into())))
2189 }
2190
2191 pub fn extensions(mut self, extensions: Option<Extensions>) -> Self {
2193 set_value!(self extensions extensions)
2194 }
2195
2196 to_array_builder!();
2197}
2198
2199component_from_builder!(ArrayBuilder);
2200
2201impl From<Array> for Schema {
2202 fn from(array: Array) -> Self {
2203 Self::Array(array)
2204 }
2205}
2206
2207impl From<ArrayBuilder> for ArrayItems {
2208 fn from(value: ArrayBuilder) -> Self {
2209 Self::RefOrSchema(Box::new(value.into()))
2210 }
2211}
2212
2213impl From<ArrayBuilder> for RefOr<Schema> {
2214 fn from(array: ArrayBuilder) -> Self {
2215 Self::T(Schema::Array(array.build()))
2216 }
2217}
2218
2219impl ToArray for Array {}
2220
2221pub trait ToArray
2223where
2224 RefOr<Schema>: From<Self>,
2225 Self: Sized,
2226{
2227 fn to_array(self) -> Array {
2229 Array::new(self)
2230 }
2231}
2232
2233#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
2238#[cfg_attr(feature = "debug", derive(Debug))]
2239#[serde(untagged)]
2240pub enum SchemaType {
2241 Type(Type),
2243 Array(Vec<Type>),
2245 AnyValue,
2248}
2249
2250impl Default for SchemaType {
2251 fn default() -> Self {
2252 Self::Type(Type::default())
2253 }
2254}
2255
2256impl From<Type> for SchemaType {
2257 fn from(value: Type) -> Self {
2258 SchemaType::new(value)
2259 }
2260}
2261
2262impl FromIterator<Type> for SchemaType {
2263 fn from_iter<T: IntoIterator<Item = Type>>(iter: T) -> Self {
2264 Self::Array(iter.into_iter().collect())
2265 }
2266}
2267
2268impl SchemaType {
2269 pub fn new(r#type: Type) -> Self {
2281 Self::Type(r#type)
2282 }
2283
2284 pub fn any() -> Self {
2289 SchemaType::AnyValue
2290 }
2291
2292 pub fn is_any_value(&self) -> bool {
2295 matches!(self, Self::AnyValue)
2296 }
2297}
2298
2299#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
2319#[cfg_attr(feature = "debug", derive(Debug))]
2320#[serde(rename_all = "lowercase")]
2321pub enum Type {
2322 #[default]
2325 Object,
2326 String,
2329 Integer,
2332 Number,
2335 Boolean,
2338 Array,
2340 Null,
2342}
2343
2344#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
2349#[cfg_attr(feature = "debug", derive(Debug))]
2350#[serde(rename_all = "lowercase", untagged)]
2351pub enum SchemaFormat {
2352 KnownFormat(KnownFormat),
2354 Custom(String),
2357}
2358
2359#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
2365#[cfg_attr(feature = "debug", derive(Debug))]
2366#[serde(rename_all = "kebab-case")]
2367pub enum KnownFormat {
2368 #[cfg(feature = "non_strict_integers")]
2370 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2371 Int8,
2372 #[cfg(feature = "non_strict_integers")]
2374 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2375 Int16,
2376 Int32,
2378 Int64,
2380 #[cfg(feature = "non_strict_integers")]
2382 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2383 UInt8,
2384 #[cfg(feature = "non_strict_integers")]
2386 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2387 UInt16,
2388 #[cfg(feature = "non_strict_integers")]
2390 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2391 UInt32,
2392 #[cfg(feature = "non_strict_integers")]
2394 #[cfg_attr(doc_cfg, doc(cfg(feature = "non_strict_integers")))]
2395 UInt64,
2396 Float,
2398 Double,
2400 Byte,
2402 Binary,
2404 Time,
2406 Date,
2408 DateTime,
2410 Duration,
2412 Password,
2414 #[cfg(feature = "uuid")]
2418 #[cfg_attr(doc_cfg, doc(cfg(feature = "uuid")))]
2419 Uuid,
2420 #[cfg(feature = "ulid")]
2422 #[cfg_attr(doc_cfg, doc(cfg(feature = "ulid")))]
2423 Ulid,
2424 #[cfg(feature = "url")]
2427 #[cfg_attr(doc_cfg, doc(cfg(feature = "url")))]
2428 Uri,
2429 #[cfg(feature = "url")]
2433 #[cfg_attr(doc_cfg, doc(cfg(feature = "url")))]
2434 UriReference,
2435 #[cfg(feature = "url")]
2438 #[cfg_attr(doc_cfg, doc(cfg(feature = "url")))]
2439 Iri,
2440 #[cfg(feature = "url")]
2444 #[cfg_attr(doc_cfg, doc(cfg(feature = "url")))]
2445 IriReference,
2446 Email,
2448 IdnEmail,
2450 Hostname,
2454 IdnHostname,
2457 Ipv4,
2459 Ipv6,
2461 UriTemplate,
2466 JsonPointer,
2468 RelativeJsonPointer,
2470 Regex,
2473}
2474
2475#[cfg(test)]
2476mod tests {
2477 use insta::assert_json_snapshot;
2478 use serde_json::{json, Value};
2479
2480 use super::*;
2481 use crate::openapi::*;
2482
2483 #[test]
2484 fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
2485 let openapi = OpenApiBuilder::new()
2486 .info(Info::new("My api", "1.0.0"))
2487 .paths(Paths::new())
2488 .components(Some(
2489 ComponentsBuilder::new()
2490 .schema("Person", Ref::new("#/components/PersonModel"))
2491 .schema(
2492 "Credential",
2493 Schema::from(
2494 ObjectBuilder::new()
2495 .property(
2496 "id",
2497 ObjectBuilder::new()
2498 .schema_type(Type::Integer)
2499 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2500 .description(Some("Id of credential"))
2501 .default(Some(json!(1i32))),
2502 )
2503 .property(
2504 "name",
2505 ObjectBuilder::new()
2506 .schema_type(Type::String)
2507 .description(Some("Name of credential")),
2508 )
2509 .property(
2510 "status",
2511 ObjectBuilder::new()
2512 .schema_type(Type::String)
2513 .default(Some(json!("Active")))
2514 .description(Some("Credential status"))
2515 .enum_values(Some([
2516 "Active",
2517 "NotActive",
2518 "Locked",
2519 "Expired",
2520 ])),
2521 )
2522 .property(
2523 "history",
2524 Array::new(Ref::from_schema_name("UpdateHistory")),
2525 )
2526 .property("tags", Object::with_type(Type::String).to_array()),
2527 ),
2528 )
2529 .build(),
2530 ))
2531 .build();
2532
2533 let serialized = serde_json::to_string_pretty(&openapi)?;
2534 println!("serialized json:\n {serialized}");
2535
2536 let value = serde_json::to_value(&openapi)?;
2537 let credential = get_json_path(&value, "components.schemas.Credential.properties");
2538 let person = get_json_path(&value, "components.schemas.Person");
2539
2540 assert!(
2541 credential.get("id").is_some(),
2542 "could not find path: components.schemas.Credential.properties.id"
2543 );
2544 assert!(
2545 credential.get("status").is_some(),
2546 "could not find path: components.schemas.Credential.properties.status"
2547 );
2548 assert!(
2549 credential.get("name").is_some(),
2550 "could not find path: components.schemas.Credential.properties.name"
2551 );
2552 assert!(
2553 credential.get("history").is_some(),
2554 "could not find path: components.schemas.Credential.properties.history"
2555 );
2556 assert_eq!(
2557 credential
2558 .get("id")
2559 .unwrap_or(&serde_json::value::Value::Null)
2560 .to_string(),
2561 r#"{"default":1,"description":"Id of credential","format":"int32","type":"integer"}"#,
2562 "components.schemas.Credential.properties.id did not match"
2563 );
2564 assert_eq!(
2565 credential
2566 .get("name")
2567 .unwrap_or(&serde_json::value::Value::Null)
2568 .to_string(),
2569 r#"{"description":"Name of credential","type":"string"}"#,
2570 "components.schemas.Credential.properties.name did not match"
2571 );
2572 assert_eq!(
2573 credential
2574 .get("status")
2575 .unwrap_or(&serde_json::value::Value::Null)
2576 .to_string(),
2577 r#"{"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"}"#,
2578 "components.schemas.Credential.properties.status did not match"
2579 );
2580 assert_eq!(
2581 credential
2582 .get("history")
2583 .unwrap_or(&serde_json::value::Value::Null)
2584 .to_string(),
2585 r###"{"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"}"###,
2586 "components.schemas.Credential.properties.history did not match"
2587 );
2588 assert_eq!(
2589 person.to_string(),
2590 r###"{"$ref":"#/components/PersonModel"}"###,
2591 "components.schemas.Person.ref did not match"
2592 );
2593
2594 Ok(())
2595 }
2596
2597 #[test]
2599 fn test_property_order() {
2600 let json_value = ObjectBuilder::new()
2601 .property(
2602 "id",
2603 ObjectBuilder::new()
2604 .schema_type(Type::Integer)
2605 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2606 .description(Some("Id of credential"))
2607 .default(Some(json!(1i32))),
2608 )
2609 .property(
2610 "name",
2611 ObjectBuilder::new()
2612 .schema_type(Type::String)
2613 .description(Some("Name of credential")),
2614 )
2615 .property(
2616 "status",
2617 ObjectBuilder::new()
2618 .schema_type(Type::String)
2619 .default(Some(json!("Active")))
2620 .description(Some("Credential status"))
2621 .enum_values(Some(["Active", "NotActive", "Locked", "Expired"])),
2622 )
2623 .property(
2624 "history",
2625 Array::new(Ref::from_schema_name("UpdateHistory")),
2626 )
2627 .property("tags", Object::with_type(Type::String).to_array())
2628 .build();
2629
2630 #[cfg(not(feature = "preserve_order"))]
2631 assert_eq!(
2632 json_value.properties.keys().collect::<Vec<_>>(),
2633 vec!["history", "id", "name", "status", "tags"]
2634 );
2635
2636 #[cfg(feature = "preserve_order")]
2637 assert_eq!(
2638 json_value.properties.keys().collect::<Vec<_>>(),
2639 vec!["id", "name", "status", "history", "tags"]
2640 );
2641 }
2642
2643 #[test]
2645 fn test_additional_properties() {
2646 let json_value = ObjectBuilder::new()
2647 .additional_properties(Some(ObjectBuilder::new().schema_type(Type::String)))
2648 .build();
2649 assert_json_snapshot!(json_value, @r#"
2650 {
2651 "type": "object",
2652 "additionalProperties": {
2653 "type": "string"
2654 }
2655 }
2656 "#);
2657
2658 let json_value = ObjectBuilder::new()
2659 .additional_properties(Some(ArrayBuilder::new().items(ArrayItems::RefOrSchema(
2660 Box::new(ObjectBuilder::new().schema_type(Type::Number).into()),
2661 ))))
2662 .build();
2663 assert_json_snapshot!(json_value, @r#"
2664 {
2665 "type": "object",
2666 "additionalProperties": {
2667 "type": "array",
2668 "items": {
2669 "type": "number"
2670 }
2671 }
2672 }
2673 "#);
2674
2675 let json_value = ObjectBuilder::new()
2676 .additional_properties(Some(Ref::from_schema_name("ComplexModel")))
2677 .build();
2678 assert_json_snapshot!(json_value, @r##"
2679 {
2680 "type": "object",
2681 "additionalProperties": {
2682 "$ref": "#/components/schemas/ComplexModel"
2683 }
2684 }
2685 "##);
2686 }
2687
2688 #[test]
2689 fn test_object_with_title() {
2690 let json_value = ObjectBuilder::new().title(Some("SomeName")).build();
2691 assert_json_snapshot!(json_value, @r#"
2692 {
2693 "type": "object",
2694 "title": "SomeName"
2695 }
2696 "#);
2697 }
2698
2699 #[test]
2700 fn derive_object_with_examples() {
2701 let json_value = ObjectBuilder::new()
2702 .examples([Some(json!({"age": 20, "name": "bob the cat"}))])
2703 .build();
2704 assert_json_snapshot!(json_value, @r#"
2705 {
2706 "type": "object",
2707 "examples": [
2708 {
2709 "age": 20,
2710 "name": "bob the cat"
2711 }
2712 ]
2713 }
2714 "#);
2715 }
2716
2717 fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
2718 path.split('.').fold(value, |acc, fragment| {
2719 acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
2720 })
2721 }
2722
2723 #[test]
2724 fn test_array_new() {
2725 let array = Array::new(
2726 ObjectBuilder::new().property(
2727 "id",
2728 ObjectBuilder::new()
2729 .schema_type(Type::Integer)
2730 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2731 .description(Some("Id of credential"))
2732 .default(Some(json!(1i32))),
2733 ),
2734 );
2735
2736 assert!(matches!(array.schema_type, SchemaType::Type(Type::Array)));
2737 }
2738
2739 #[test]
2740 fn test_array_builder() {
2741 let array: Array = ArrayBuilder::new()
2742 .items(
2743 ObjectBuilder::new().property(
2744 "id",
2745 ObjectBuilder::new()
2746 .schema_type(Type::Integer)
2747 .format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
2748 .description(Some("Id of credential"))
2749 .default(Some(json!(1i32))),
2750 ),
2751 )
2752 .build();
2753
2754 assert!(matches!(array.schema_type, SchemaType::Type(Type::Array)));
2755 }
2756
2757 #[test]
2758 fn reserialize_deserialized_schema_components() {
2759 let components = ComponentsBuilder::new()
2760 .schemas_from_iter(vec![(
2761 "Comp",
2762 Schema::from(
2763 ObjectBuilder::new()
2764 .property("name", ObjectBuilder::new().schema_type(Type::String))
2765 .required("name"),
2766 ),
2767 )])
2768 .responses_from_iter(vec![(
2769 "200",
2770 ResponseBuilder::new().description("Okay").build(),
2771 )])
2772 .security_scheme(
2773 "TLS",
2774 SecurityScheme::MutualTls {
2775 description: None,
2776 deprecated: None,
2777 extensions: None,
2778 },
2779 )
2780 .build();
2781
2782 let serialized_components = serde_json::to_string(&components).unwrap();
2783
2784 let deserialized_components: Components =
2785 serde_json::from_str(serialized_components.as_str()).unwrap();
2786
2787 assert_eq!(
2788 serialized_components,
2789 serde_json::to_string(&deserialized_components).unwrap()
2790 )
2791 }
2792
2793 #[test]
2794 fn reserialize_deserialized_object_component() {
2795 let prop = ObjectBuilder::new()
2796 .property("name", ObjectBuilder::new().schema_type(Type::String))
2797 .required("name")
2798 .build();
2799
2800 let serialized_components = serde_json::to_string(&prop).unwrap();
2801 let deserialized_components: Object =
2802 serde_json::from_str(serialized_components.as_str()).unwrap();
2803
2804 assert_eq!(
2805 serialized_components,
2806 serde_json::to_string(&deserialized_components).unwrap()
2807 )
2808 }
2809
2810 #[test]
2811 fn reserialize_deserialized_property() {
2812 let prop = ObjectBuilder::new().schema_type(Type::String).build();
2813
2814 let serialized_components = serde_json::to_string(&prop).unwrap();
2815 let deserialized_components: Object =
2816 serde_json::from_str(serialized_components.as_str()).unwrap();
2817
2818 assert_eq!(
2819 serialized_components,
2820 serde_json::to_string(&deserialized_components).unwrap()
2821 )
2822 }
2823
2824 #[test]
2825 fn serialize_deserialize_array_within_ref_or_t_object_builder() {
2826 let ref_or_schema = RefOr::T(Schema::Object(
2827 ObjectBuilder::new()
2828 .property(
2829 "test",
2830 RefOr::T(Schema::Array(
2831 ArrayBuilder::new()
2832 .items(RefOr::T(Schema::Object(
2833 ObjectBuilder::new()
2834 .property("element", RefOr::Ref(Ref::new("#/test")))
2835 .build(),
2836 )))
2837 .build(),
2838 )),
2839 )
2840 .build(),
2841 ));
2842
2843 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2844 println!("----------------------------");
2845 println!("{json_str}");
2846
2847 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2848
2849 let json_de_str = serde_json::to_string(&deserialized).expect("");
2850 println!("----------------------------");
2851 println!("{json_de_str}");
2852
2853 assert_eq!(json_str, json_de_str);
2854 }
2855
2856 #[test]
2857 fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
2858 let ref_or_schema = RefOr::T(Schema::Object(
2859 ObjectBuilder::new()
2860 .property(
2861 "test",
2862 RefOr::T(Schema::OneOf(
2863 OneOfBuilder::new()
2864 .item(Schema::Array(
2865 ArrayBuilder::new()
2866 .items(RefOr::T(Schema::Object(
2867 ObjectBuilder::new()
2868 .property("element", RefOr::Ref(Ref::new("#/test")))
2869 .build(),
2870 )))
2871 .build(),
2872 ))
2873 .item(Schema::Array(
2874 ArrayBuilder::new()
2875 .items(RefOr::T(Schema::Object(
2876 ObjectBuilder::new()
2877 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
2878 .build(),
2879 )))
2880 .build(),
2881 ))
2882 .build(),
2883 )),
2884 )
2885 .build(),
2886 ));
2887
2888 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2889 println!("----------------------------");
2890 println!("{json_str}");
2891
2892 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2893
2894 let json_de_str = serde_json::to_string(&deserialized).expect("");
2895 println!("----------------------------");
2896 println!("{json_de_str}");
2897
2898 assert_eq!(json_str, json_de_str);
2899 }
2900
2901 #[test]
2902 fn serialize_deserialize_all_of_of_within_ref_or_t_object_builder() {
2903 let ref_or_schema = RefOr::T(Schema::Object(
2904 ObjectBuilder::new()
2905 .property(
2906 "test",
2907 RefOr::T(Schema::AllOf(
2908 AllOfBuilder::new()
2909 .item(Schema::Array(
2910 ArrayBuilder::new()
2911 .items(RefOr::T(Schema::Object(
2912 ObjectBuilder::new()
2913 .property("element", RefOr::Ref(Ref::new("#/test")))
2914 .build(),
2915 )))
2916 .build(),
2917 ))
2918 .item(RefOr::T(Schema::Object(
2919 ObjectBuilder::new()
2920 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
2921 .build(),
2922 )))
2923 .build(),
2924 )),
2925 )
2926 .build(),
2927 ));
2928
2929 let json_str = serde_json::to_string(&ref_or_schema).expect("");
2930 println!("----------------------------");
2931 println!("{json_str}");
2932
2933 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
2934
2935 let json_de_str = serde_json::to_string(&deserialized).expect("");
2936 println!("----------------------------");
2937 println!("{json_de_str}");
2938
2939 assert_eq!(json_str, json_de_str);
2940 }
2941
2942 #[test]
2943 fn deserialize_reserialize_one_of_default_type() {
2944 let a = OneOfBuilder::new()
2945 .item(Schema::Array(
2946 ArrayBuilder::new()
2947 .items(RefOr::T(Schema::Object(
2948 ObjectBuilder::new()
2949 .property("element", RefOr::Ref(Ref::new("#/test")))
2950 .build(),
2951 )))
2952 .build(),
2953 ))
2954 .item(Schema::Array(
2955 ArrayBuilder::new()
2956 .items(RefOr::T(Schema::Object(
2957 ObjectBuilder::new()
2958 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
2959 .build(),
2960 )))
2961 .build(),
2962 ))
2963 .build();
2964
2965 let serialized_json = serde_json::to_string(&a).expect("should serialize to json");
2966 let b: OneOf = serde_json::from_str(&serialized_json).expect("should deserialize OneOf");
2967 let reserialized_json = serde_json::to_string(&b).expect("reserialized json");
2968
2969 println!("{serialized_json}");
2970 println!("{reserialized_json}",);
2971 assert_eq!(serialized_json, reserialized_json);
2972 }
2973
2974 #[test]
2975 fn serialize_deserialize_any_of_of_within_ref_or_t_object_builder() {
2976 let ref_or_schema = RefOr::T(Schema::Object(
2977 ObjectBuilder::new()
2978 .property(
2979 "test",
2980 RefOr::T(Schema::AnyOf(
2981 AnyOfBuilder::new()
2982 .item(Schema::Array(
2983 ArrayBuilder::new()
2984 .items(RefOr::T(Schema::Object(
2985 ObjectBuilder::new()
2986 .property("element", RefOr::Ref(Ref::new("#/test")))
2987 .build(),
2988 )))
2989 .build(),
2990 ))
2991 .item(RefOr::T(Schema::Object(
2992 ObjectBuilder::new()
2993 .property("foobar", RefOr::Ref(Ref::new("#/foobar")))
2994 .build(),
2995 )))
2996 .build(),
2997 )),
2998 )
2999 .build(),
3000 ));
3001
3002 let json_str = serde_json::to_string(&ref_or_schema).expect("");
3003 println!("----------------------------");
3004 println!("{json_str}");
3005
3006 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
3007
3008 let json_de_str = serde_json::to_string(&deserialized).expect("");
3009 println!("----------------------------");
3010 println!("{json_de_str}");
3011 assert!(json_str.contains("\"anyOf\""));
3012 assert_eq!(json_str, json_de_str);
3013 }
3014
3015 #[test]
3016 fn serialize_deserialize_schema_array_ref_or_t() {
3017 let ref_or_schema = RefOr::T(Schema::Array(
3018 ArrayBuilder::new()
3019 .items(RefOr::T(Schema::Object(
3020 ObjectBuilder::new()
3021 .property("element", RefOr::Ref(Ref::new("#/test")))
3022 .build(),
3023 )))
3024 .build(),
3025 ));
3026
3027 let json_str = serde_json::to_string(&ref_or_schema).expect("");
3028 println!("----------------------------");
3029 println!("{json_str}");
3030
3031 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
3032
3033 let json_de_str = serde_json::to_string(&deserialized).expect("");
3034 println!("----------------------------");
3035 println!("{json_de_str}");
3036
3037 assert_eq!(json_str, json_de_str);
3038 }
3039
3040 #[test]
3041 fn serialize_deserialize_schema_array_builder() {
3042 let ref_or_schema = ArrayBuilder::new()
3043 .items(RefOr::T(Schema::Object(
3044 ObjectBuilder::new()
3045 .property("element", RefOr::Ref(Ref::new("#/test")))
3046 .build(),
3047 )))
3048 .build();
3049
3050 let json_str = serde_json::to_string(&ref_or_schema).expect("");
3051 println!("----------------------------");
3052 println!("{json_str}");
3053
3054 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
3055
3056 let json_de_str = serde_json::to_string(&deserialized).expect("");
3057 println!("----------------------------");
3058 println!("{json_de_str}");
3059
3060 assert_eq!(json_str, json_de_str);
3061 }
3062
3063 #[test]
3064 fn serialize_deserialize_schema_with_additional_properties() {
3065 let schema = Schema::Object(
3066 ObjectBuilder::new()
3067 .property(
3068 "map",
3069 ObjectBuilder::new()
3070 .additional_properties(Some(AdditionalProperties::FreeForm(true))),
3071 )
3072 .build(),
3073 );
3074
3075 let json_str = serde_json::to_string(&schema).unwrap();
3076 println!("----------------------------");
3077 println!("{json_str}");
3078
3079 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
3080
3081 let json_de_str = serde_json::to_string(&deserialized).unwrap();
3082 println!("----------------------------");
3083 println!("{json_de_str}");
3084
3085 assert_eq!(json_str, json_de_str);
3086 }
3087
3088 #[test]
3089 fn serialize_deserialize_schema_with_additional_properties_object() {
3090 let schema = Schema::Object(
3091 ObjectBuilder::new()
3092 .property(
3093 "map",
3094 ObjectBuilder::new().additional_properties(Some(
3095 ObjectBuilder::new().property("name", Object::with_type(Type::String)),
3096 )),
3097 )
3098 .build(),
3099 );
3100
3101 let json_str = serde_json::to_string(&schema).unwrap();
3102 println!("----------------------------");
3103 println!("{json_str}");
3104
3105 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
3106
3107 let json_de_str = serde_json::to_string(&deserialized).unwrap();
3108 println!("----------------------------");
3109 println!("{json_de_str}");
3110
3111 assert_eq!(json_str, json_de_str);
3112 }
3113
3114 #[test]
3115 fn serialize_discriminator_with_mapping() {
3116 let mut discriminator = Discriminator::new("type");
3117 discriminator.mapping = [("int".to_string(), "#/components/schemas/MyInt".to_string())]
3118 .into_iter()
3119 .collect::<BTreeMap<_, _>>();
3120 let one_of = OneOfBuilder::new()
3121 .item(Ref::from_schema_name("MyInt"))
3122 .discriminator(Some(discriminator))
3123 .build();
3124 assert_json_snapshot!(one_of, @r##"
3125 {
3126 "oneOf": [
3127 {
3128 "$ref": "#/components/schemas/MyInt"
3129 }
3130 ],
3131 "discriminator": {
3132 "propertyName": "type",
3133 "mapping": {
3134 "int": "#/components/schemas/MyInt"
3135 }
3136 }
3137 }
3138 "##);
3139 }
3140
3141 #[test]
3142 fn serialize_deserialize_object_with_multiple_schema_types() {
3143 let object = ObjectBuilder::new()
3144 .schema_type(SchemaType::from_iter([Type::Object, Type::Null]))
3145 .build();
3146
3147 let json_str = serde_json::to_string(&object).unwrap();
3148 println!("----------------------------");
3149 println!("{json_str}");
3150
3151 let deserialized: Object = serde_json::from_str(&json_str).unwrap();
3152
3153 let json_de_str = serde_json::to_string(&deserialized).unwrap();
3154 println!("----------------------------");
3155 println!("{json_de_str}");
3156
3157 assert_eq!(json_str, json_de_str);
3158 }
3159
3160 #[test]
3161 fn object_with_extensions() {
3162 let expected = json!("value");
3163 let extensions = extensions::ExtensionsBuilder::new()
3164 .add("x-some-extension", expected.clone())
3165 .build();
3166 let json_value = ObjectBuilder::new().extensions(Some(extensions)).build();
3167
3168 let value = serde_json::to_value(&json_value).unwrap();
3169 assert_eq!(value.get("x-some-extension"), Some(&expected));
3170 }
3171
3172 #[test]
3173 fn array_with_extensions() {
3174 let expected = json!("value");
3175 let extensions = extensions::ExtensionsBuilder::new()
3176 .add("x-some-extension", expected.clone())
3177 .build();
3178 let json_value = ArrayBuilder::new().extensions(Some(extensions)).build();
3179
3180 let value = serde_json::to_value(&json_value).unwrap();
3181 assert_eq!(value.get("x-some-extension"), Some(&expected));
3182 }
3183
3184 #[test]
3185 fn oneof_with_extensions() {
3186 let expected = json!("value");
3187 let extensions = extensions::ExtensionsBuilder::new()
3188 .add("x-some-extension", expected.clone())
3189 .build();
3190 let json_value = OneOfBuilder::new().extensions(Some(extensions)).build();
3191
3192 let value = serde_json::to_value(&json_value).unwrap();
3193 assert_eq!(value.get("x-some-extension"), Some(&expected));
3194 }
3195
3196 #[test]
3197 fn allof_with_extensions() {
3198 let expected = json!("value");
3199 let extensions = extensions::ExtensionsBuilder::new()
3200 .add("x-some-extension", expected.clone())
3201 .build();
3202 let json_value = AllOfBuilder::new().extensions(Some(extensions)).build();
3203
3204 let value = serde_json::to_value(&json_value).unwrap();
3205 assert_eq!(value.get("x-some-extension"), Some(&expected));
3206 }
3207
3208 #[test]
3209 fn anyof_with_extensions() {
3210 let expected = json!("value");
3211 let extensions = extensions::ExtensionsBuilder::new()
3212 .add("x-some-extension", expected.clone())
3213 .build();
3214 let json_value = AnyOfBuilder::new().extensions(Some(extensions)).build();
3215
3216 let value = serde_json::to_value(&json_value).unwrap();
3217 assert_eq!(value.get("x-some-extension"), Some(&expected));
3218 }
3219}