1mod all_of;
6mod any_of;
7mod array;
8mod number;
9mod object;
10mod one_of;
11
12use std::ops::{Deref, DerefMut};
13
14pub use all_of::AllOf;
15pub use any_of::AnyOf;
16pub use array::{Array, ArrayItems};
17pub use number::Number;
18pub use object::Object;
19pub use one_of::OneOf;
20use serde::{Deserialize, Serialize};
21
22use crate::{PropMap, RefOr};
23
24#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
26#[serde(rename_all = "camelCase")]
27pub struct Schemas(pub PropMap<String, RefOr<Schema>>);
28
29impl<K, R> From<PropMap<K, R>> for Schemas
30where
31 K: Into<String>,
32 R: Into<RefOr<Schema>>,
33{
34 fn from(inner: PropMap<K, R>) -> Self {
35 Self(
36 inner
37 .into_iter()
38 .map(|(k, v)| (k.into(), v.into()))
39 .collect(),
40 )
41 }
42}
43impl<K, R, const N: usize> From<[(K, R); N]> for Schemas
44where
45 K: Into<String>,
46 R: Into<RefOr<Schema>>,
47{
48 fn from(inner: [(K, R); N]) -> Self {
49 Self(
50 <[(K, R)]>::into_vec(Box::new(inner))
51 .into_iter()
52 .map(|(k, v)| (k.into(), v.into()))
53 .collect(),
54 )
55 }
56}
57
58impl Deref for Schemas {
59 type Target = PropMap<String, RefOr<Schema>>;
60
61 fn deref(&self) -> &Self::Target {
62 &self.0
63 }
64}
65
66impl DerefMut for Schemas {
67 fn deref_mut(&mut self) -> &mut Self::Target {
68 &mut self.0
69 }
70}
71
72impl IntoIterator for Schemas {
73 type Item = (String, RefOr<Schema>);
74 type IntoIter = <PropMap<String, RefOr<Schema>> as IntoIterator>::IntoIter;
75
76 fn into_iter(self) -> Self::IntoIter {
77 self.0.into_iter()
78 }
79}
80
81impl Schemas {
82 #[must_use]
84 pub fn new() -> Self {
85 Default::default()
86 }
87 #[must_use]
89 pub fn schema<K: Into<String>, V: Into<RefOr<Schema>>>(mut self, key: K, value: V) -> Self {
90 self.insert(key, value);
91 self
92 }
93 pub fn insert<K: Into<String>, V: Into<RefOr<Schema>>>(&mut self, key: K, value: V) {
95 self.0.insert(key.into(), value.into());
96 }
97 pub fn append(&mut self, other: &mut Self) {
102 let items = std::mem::take(&mut other.0);
103 for item in items {
104 self.insert(item.0, item.1);
105 }
106 }
107 pub fn extend<I, K, V>(&mut self, iter: I)
109 where
110 I: IntoIterator<Item = (K, V)>,
111 K: Into<String>,
112 V: Into<RefOr<Schema>>,
113 {
114 for (k, v) in iter.into_iter() {
115 self.insert(k, v);
116 }
117 }
118}
119
120#[must_use]
125pub fn empty() -> Schema {
126 Schema::object(
127 Object::new()
128 .schema_type(SchemaType::AnyValue)
129 .default_value(serde_json::Value::Null),
130 )
131}
132
133#[non_exhaustive]
138#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
139#[serde(untagged, rename_all = "camelCase")]
140pub enum Schema {
141 Array(Array),
144 Object(Box<Object>),
147 OneOf(OneOf),
153
154 AllOf(AllOf),
158
159 AnyOf(AnyOf),
163}
164
165impl Default for Schema {
166 fn default() -> Self {
167 Self::Object(Default::default())
168 }
169}
170
171impl Schema {
172 #[must_use]
174 pub fn object(obj: Object) -> Self {
175 Self::Object(Box::new(obj))
176 }
177}
178
179#[non_exhaustive]
184#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
185#[serde(rename_all = "camelCase")]
186pub struct Discriminator {
187 pub property_name: String,
190
191 #[serde(skip_serializing_if = "PropMap::is_empty", default)]
195 pub mapping: PropMap<String, String>,
196
197 #[serde(skip_serializing_if = "Option::is_none", default)]
205 pub default_mapping: Option<String>,
206
207 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
209 pub extensions: PropMap<String, serde_json::Value>,
210}
211
212impl Discriminator {
213 pub fn new<I: Into<String>>(property_name: I) -> Self {
223 Self {
224 property_name: property_name.into(),
225 mapping: PropMap::new(),
226 default_mapping: None,
227 extensions: PropMap::new(),
228 }
229 }
230
231 #[must_use]
233 pub fn add_mapping<K: Into<String>, V: Into<String>>(mut self, value: K, schema: V) -> Self {
234 self.mapping.insert(value.into(), schema.into());
235 self
236 }
237
238 #[must_use]
241 pub fn default_mapping<I: Into<String>>(mut self, default_mapping: I) -> Self {
242 self.default_mapping = Some(default_mapping.into());
243 self
244 }
245
246 #[must_use]
248 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
249 self.extensions = extensions;
250 self
251 }
252}
253
254#[allow(clippy::trivially_copy_pass_by_ref)]
255fn is_false(value: &bool) -> bool {
256 !*value
257}
258
259#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
263#[serde(untagged)]
264pub enum AdditionalProperties<T> {
265 RefOr(RefOr<T>),
267 FreeForm(bool),
269}
270
271impl<T> From<RefOr<T>> for AdditionalProperties<T> {
272 fn from(value: RefOr<T>) -> Self {
273 Self::RefOr(value)
274 }
275}
276
277impl From<Object> for AdditionalProperties<Schema> {
278 fn from(value: Object) -> Self {
279 Self::RefOr(RefOr::Type(Schema::object(value)))
280 }
281}
282
283impl From<Array> for AdditionalProperties<Schema> {
284 fn from(value: Array) -> Self {
285 Self::RefOr(RefOr::Type(Schema::Array(value)))
286 }
287}
288
289impl From<Ref> for AdditionalProperties<Schema> {
290 fn from(value: Ref) -> Self {
291 Self::RefOr(RefOr::Ref(value))
292 }
293}
294
295impl From<OneOf> for AdditionalProperties<Schema> {
296 fn from(value: OneOf) -> Self {
297 Self::RefOr(RefOr::Type(Schema::OneOf(value)))
298 }
299}
300
301#[non_exhaustive]
306#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
307pub struct Ref {
308 #[serde(rename = "$ref")]
310 pub ref_location: String,
311
312 #[serde(skip_serializing_if = "String::is_empty", default)]
316 pub description: String,
317
318 #[serde(skip_serializing_if = "String::is_empty", default)]
321 pub summary: String,
322}
323
324impl Ref {
325 #[must_use]
328 pub fn new<I: Into<String>>(ref_location: I) -> Self {
329 Self {
330 ref_location: ref_location.into(),
331 ..Default::default()
332 }
333 }
334
335 #[must_use]
338 pub fn from_schema_name<I: Into<String>>(schema_name: I) -> Self {
339 Self::new(format!("#/components/schemas/{}", schema_name.into()))
340 }
341
342 #[must_use]
345 pub fn from_response_name<I: Into<String>>(response_name: I) -> Self {
346 Self::new(format!("#/components/responses/{}", response_name.into()))
347 }
348
349 #[must_use]
351 pub fn ref_location(mut self, ref_location: String) -> Self {
352 self.ref_location = ref_location;
353 self
354 }
355
356 #[must_use]
359 pub fn ref_location_from_schema_name<S: Into<String>>(mut self, schema_name: S) -> Self {
360 self.ref_location = format!("#/components/schemas/{}", schema_name.into());
361 self
362 }
363
364 #[must_use]
370 pub fn description<S: Into<String>>(mut self, description: S) -> Self {
371 self.description = description.into();
372 self
373 }
374
375 #[must_use]
379 pub fn summary<S: Into<String>>(mut self, summary: S) -> Self {
380 self.summary = summary.into();
381 self
382 }
383
384 #[must_use]
386 pub fn to_array(self) -> Array {
387 Array::new().items(self)
388 }
389}
390
391impl From<Ref> for RefOr<Schema> {
392 fn from(r: Ref) -> Self {
393 Self::Ref(r)
394 }
395}
396
397impl<T> From<T> for RefOr<T> {
398 fn from(t: T) -> Self {
399 Self::Type(t)
400 }
401}
402
403impl Default for RefOr<Schema> {
404 fn default() -> Self {
405 Self::Type(Schema::object(Object::new()))
406 }
407}
408
409#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
413#[serde(untagged)]
414pub enum SchemaType {
415 Basic(BasicType),
417 Array(Vec<BasicType>),
419 AnyValue,
422}
423
424impl Default for SchemaType {
425 fn default() -> Self {
426 Self::Basic(BasicType::default())
427 }
428}
429
430impl From<BasicType> for SchemaType {
431 fn from(value: BasicType) -> Self {
432 Self::basic(value)
433 }
434}
435
436impl FromIterator<BasicType> for SchemaType {
437 fn from_iter<T: IntoIterator<Item = BasicType>>(iter: T) -> Self {
438 Self::Array(iter.into_iter().collect())
439 }
440}
441impl SchemaType {
442 #[must_use]
454 pub fn basic(r#type: BasicType) -> Self {
455 Self::Basic(r#type)
456 }
457
458 #[must_use]
462 pub fn any() -> Self {
463 Self::AnyValue
464 }
465
466 #[must_use]
469 pub fn is_any_value(&self) -> bool {
470 matches!(self, Self::AnyValue)
471 }
472}
473
474#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
494#[serde(rename_all = "lowercase")]
495pub enum BasicType {
496 #[default]
498 Object,
499 String,
502 Integer,
505 Number,
508 Boolean,
511 Array,
513 Null,
515}
516
517#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
523#[serde(rename_all = "lowercase", untagged)]
524pub enum SchemaFormat {
525 KnownFormat(KnownFormat),
527 Custom(String),
530}
531
532#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
538#[serde(rename_all = "kebab-case")]
539pub enum KnownFormat {
540 Int8,
542 Int16,
544 Int32,
546 Int64,
548 #[serde(rename = "uint8")]
550 UInt8,
551 #[serde(rename = "uint16")]
553 UInt16,
554 #[serde(rename = "uint32")]
556 UInt32,
557 #[serde(rename = "uint64")]
559 UInt64,
560 Float,
562 Double,
564 Byte,
566 Binary,
568 Time,
570 Date,
572 DateTime,
574 Duration,
576 Password,
578 String,
580 #[cfg(any(feature = "decimal", feature = "decimal-float"))]
584 #[cfg_attr(docsrs, doc(cfg(any(feature = "decimal", feature = "decimal-float"))))]
585 Decimal,
586 #[cfg(feature = "ulid")]
588 #[cfg_attr(docsrs, doc(cfg(feature = "ulid")))]
589 Ulid,
590
591 #[cfg(feature = "uuid")]
593 #[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
594 Uuid,
595 #[cfg(feature = "url")]
599 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
600 Url,
601 #[cfg(feature = "url")]
605 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
606 UriReference,
607 #[cfg(feature = "url")]
610 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
611 Iri,
612 #[cfg(feature = "url")]
616 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
617 IriReference,
618 Email,
620 IdnEmail,
622 Hostname,
626 IdnHostname,
629 Ipv4,
631 Ipv6,
633 UriTemplate,
638 JsonPointer,
640 RelativeJsonPointer,
642 Regex,
645}
646
647#[cfg(test)]
648mod tests {
649 use assert_json_diff::assert_json_eq;
650 use serde_json::{Value, json};
651
652 use super::*;
653 use crate::*;
654
655 #[test]
656 fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
657 let openapi = OpenApi::new("My api", "1.0.0").components(
658 Components::new()
659 .add_schema("Person", Ref::new("#/components/PersonModel"))
660 .add_schema(
661 "Credential",
662 Schema::from(
663 Object::new()
664 .property(
665 "id",
666 Object::new()
667 .schema_type(BasicType::Integer)
668 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
669 .description("Id of credential")
670 .default_value(json!(1i32)),
671 )
672 .property(
673 "name",
674 Object::new()
675 .schema_type(BasicType::String)
676 .description("Name of credential"),
677 )
678 .property(
679 "status",
680 Object::new()
681 .schema_type(BasicType::String)
682 .default_value(json!("Active"))
683 .description("Credential status")
684 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
685 )
686 .property(
687 "history",
688 Array::new().items(Ref::from_schema_name("UpdateHistory")),
689 )
690 .property("tags", Object::with_type(BasicType::String).to_array()),
691 ),
692 ),
693 );
694
695 let serialized = serde_json::to_string_pretty(&openapi)?;
696 println!("serialized json:\n {serialized}");
697
698 let value = serde_json::to_value(&openapi)?;
699 let credential = get_json_path(&value, "components.schemas.Credential.properties");
700 let person = get_json_path(&value, "components.schemas.Person");
701
702 assert!(
703 credential.get("id").is_some(),
704 "could not find path: components.schemas.Credential.properties.id"
705 );
706 assert!(
707 credential.get("status").is_some(),
708 "could not find path: components.schemas.Credential.properties.status"
709 );
710 assert!(
711 credential.get("name").is_some(),
712 "could not find path: components.schemas.Credential.properties.name"
713 );
714 assert!(
715 credential.get("history").is_some(),
716 "could not find path: components.schemas.Credential.properties.history"
717 );
718 assert_json_eq!(
719 credential
720 .get("id")
721 .unwrap_or(&serde_json::value::Value::Null),
722 json!({"type":"integer","format":"int32","description":"Id of credential","default":1})
723 );
724 assert_json_eq!(
725 credential
726 .get("name")
727 .unwrap_or(&serde_json::value::Value::Null),
728 json!({"type":"string","description":"Name of credential"})
729 );
730 assert_json_eq!(
731 credential
732 .get("status")
733 .unwrap_or(&serde_json::value::Value::Null),
734 json!({"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"})
735 );
736 assert_json_eq!(
737 credential
738 .get("history")
739 .unwrap_or(&serde_json::value::Value::Null),
740 json!({"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"})
741 );
742 assert_eq!(person, &json!({"$ref":"#/components/PersonModel"}));
743
744 Ok(())
745 }
746
747 #[test]
749 fn test_property_order() {
750 let json_value = Object::new()
751 .property(
752 "id",
753 Object::new()
754 .schema_type(BasicType::Integer)
755 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
756 .description("Id of credential")
757 .default_value(json!(1i32)),
758 )
759 .property(
760 "name",
761 Object::new()
762 .schema_type(BasicType::String)
763 .description("Name of credential"),
764 )
765 .property(
766 "status",
767 Object::new()
768 .schema_type(BasicType::String)
769 .default_value(json!("Active"))
770 .description("Credential status")
771 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
772 )
773 .property(
774 "history",
775 Array::new().items(Ref::from_schema_name("UpdateHistory")),
776 )
777 .property("tags", Object::with_type(BasicType::String).to_array());
778
779 #[cfg(not(feature = "preserve-order"))]
780 assert_eq!(
781 json_value.properties.keys().collect::<Vec<_>>(),
782 vec!["history", "id", "name", "status", "tags"]
783 );
784
785 #[cfg(feature = "preserve-order")]
786 assert_eq!(
787 json_value.properties.keys().collect::<Vec<_>>(),
788 vec!["id", "name", "status", "history", "tags"]
789 );
790 }
791
792 #[test]
794 fn test_additional_properties() {
795 let json_value =
796 Object::new().additional_properties(Object::new().schema_type(BasicType::String));
797 assert_json_eq!(
798 json_value,
799 json!({
800 "type": "object",
801 "additionalProperties": {
802 "type": "string"
803 }
804 })
805 );
806
807 let json_value = Object::new().additional_properties(
808 Array::new().items(Object::new().schema_type(BasicType::Number)),
809 );
810 assert_json_eq!(
811 json_value,
812 json!({
813 "type": "object",
814 "additionalProperties": {
815 "items": {
816 "type": "number",
817 },
818 "type": "array",
819 }
820 })
821 );
822
823 let json_value = Object::new().additional_properties(Ref::from_schema_name("ComplexModel"));
824 assert_json_eq!(
825 json_value,
826 json!({
827 "type": "object",
828 "additionalProperties": {
829 "$ref": "#/components/schemas/ComplexModel"
830 }
831 })
832 )
833 }
834
835 #[test]
836 fn test_object_with_name() {
837 let json_value = Object::new().name("SomeName");
838 assert_json_eq!(
839 json_value,
840 json!({
841 "type": "object",
842 "name": "SomeName"
843 })
844 );
845 }
846
847 #[test]
848 fn test_derive_object_with_examples() {
849 let expected = r#"{"type":"object","examples":[{"age":20,"name":"bob the cat"}]}"#;
850 let json_value = Object::new().examples([json!({"age": 20, "name": "bob the cat"})]);
851
852 let value_string = serde_json::to_string(&json_value).unwrap();
853 assert_eq!(
854 value_string, expected,
855 "value string != expected string, {value_string} != {expected}"
856 );
857 }
858
859 fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
860 path.split('.').fold(value, |acc, fragment| {
861 acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
862 })
863 }
864
865 #[test]
866 fn test_array_new() {
867 let array = Array::new().items(
868 Object::new().property(
869 "id",
870 Object::new()
871 .schema_type(BasicType::Integer)
872 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
873 .description("Id of credential")
874 .default_value(json!(1i32)),
875 ),
876 );
877
878 assert!(matches!(
879 array.schema_type,
880 SchemaType::Basic(BasicType::Array)
881 ));
882 }
883
884 #[test]
885 fn test_array_builder() {
886 let array: Array = Array::new().items(
887 Object::new().property(
888 "id",
889 Object::new()
890 .schema_type(BasicType::Integer)
891 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
892 .description("Id of credential")
893 .default_value(json!(1i32)),
894 ),
895 );
896
897 assert!(matches!(
898 array.schema_type,
899 SchemaType::Basic(BasicType::Array)
900 ));
901 }
902
903 #[test]
904 fn reserialize_deserialized_schema_components() {
905 let components = Components::new()
906 .extend_schemas(vec![(
907 "Comp",
908 Schema::from(
909 Object::new()
910 .property("name", Object::new().schema_type(BasicType::String))
911 .required("name"),
912 ),
913 )])
914 .response("204", Response::new("No Content"))
915 .extend_responses(vec![("200", Response::new("Okay"))])
916 .add_security_scheme(
917 "TLS",
918 SecurityScheme::MutualTls {
919 description: None,
920 deprecated: None,
921 },
922 )
923 .extend_security_schemes(vec![(
924 "APIKey",
925 SecurityScheme::Http(security::Http::default()),
926 )]);
927
928 let serialized_components = serde_json::to_string(&components).unwrap();
929
930 let deserialized_components: Components =
931 serde_json::from_str(serialized_components.as_str()).unwrap();
932
933 assert_eq!(
934 serialized_components,
935 serde_json::to_string(&deserialized_components).unwrap()
936 )
937 }
938
939 #[test]
940 fn reserialize_deserialized_object_component() {
941 let prop = Object::new()
942 .property("name", Object::new().schema_type(BasicType::String))
943 .required("name");
944
945 let serialized_components = serde_json::to_string(&prop).unwrap();
946 let deserialized_components: Object =
947 serde_json::from_str(serialized_components.as_str()).unwrap();
948
949 assert_eq!(
950 serialized_components,
951 serde_json::to_string(&deserialized_components).unwrap()
952 )
953 }
954
955 #[test]
956 fn reserialize_deserialized_property() {
957 let prop = Object::new().schema_type(BasicType::String);
958
959 let serialized_components = serde_json::to_string(&prop).unwrap();
960 let deserialized_components: Object =
961 serde_json::from_str(serialized_components.as_str()).unwrap();
962
963 assert_eq!(
964 serialized_components,
965 serde_json::to_string(&deserialized_components).unwrap()
966 )
967 }
968
969 #[test]
970 fn serialize_deserialize_array_within_ref_or_t_object_builder() {
971 let ref_or_schema = RefOr::Type(Schema::object(Object::new().property(
972 "test",
973 RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
974 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
975 )))),
976 )));
977
978 let json_str = serde_json::to_string(&ref_or_schema).expect("");
979 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
980 let json_de_str = serde_json::to_string(&deserialized).expect("");
981 assert_eq!(json_str, json_de_str);
982 }
983
984 #[test]
985 fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
986 let ref_or_schema = RefOr::Type(Schema::object(
987 Object::new().property(
988 "test",
989 RefOr::Type(Schema::OneOf(
990 OneOf::new()
991 .item(Schema::Array(Array::new().items(RefOr::Type(
992 Schema::object(
993 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
994 ),
995 ))))
996 .item(Schema::Array(Array::new().items(RefOr::Type(
997 Schema::object(
998 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
999 ),
1000 )))),
1001 )),
1002 ),
1003 ));
1004
1005 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1006 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1007 let json_de_str = serde_json::to_string(&deserialized).expect("");
1008 assert_eq!(json_str, json_de_str);
1009 }
1010
1011 #[test]
1012 fn serialize_deserialize_all_of_of_within_ref_or_t_object() {
1013 let ref_or_schema = RefOr::Type(Schema::object(
1014 Object::new().property(
1015 "test",
1016 RefOr::Type(Schema::AllOf(
1017 AllOf::new()
1018 .item(Schema::Array(Array::new().items(RefOr::Type(
1019 Schema::object(
1020 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1021 ),
1022 ))))
1023 .item(RefOr::Type(Schema::object(
1024 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
1025 ))),
1026 )),
1027 ),
1028 ));
1029
1030 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1031 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1032 let json_de_str = serde_json::to_string(&deserialized).expect("");
1033 assert_eq!(json_str, json_de_str);
1034 }
1035
1036 #[test]
1037 fn serialize_deserialize_any_of_of_within_ref_or_t_object() {
1038 let ref_or_schema = RefOr::Type(Schema::object(
1039 Object::new().property(
1040 "test",
1041 RefOr::Type(Schema::AnyOf(
1042 AnyOf::new()
1043 .item(Schema::Array(Array::new().items(RefOr::Type(
1044 Schema::object(
1045 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1046 ),
1047 ))))
1048 .item(RefOr::Type(Schema::object(
1049 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
1050 ))),
1051 )),
1052 ),
1053 ));
1054
1055 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1056 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1057 let json_de_str = serde_json::to_string(&deserialized).expect("");
1058 assert!(json_str.contains("\"anyOf\""));
1059 assert_eq!(json_str, json_de_str);
1060 }
1061
1062 #[test]
1063 fn serialize_deserialize_schema_array_ref_or_t() {
1064 let ref_or_schema = RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
1065 Schema::Object(Box::new(
1066 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1067 )),
1068 ))));
1069
1070 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1071 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1072 let json_de_str = serde_json::to_string(&deserialized).expect("");
1073 assert_eq!(json_str, json_de_str);
1074 }
1075
1076 #[test]
1077 fn serialize_deserialize_schema_array() {
1078 let ref_or_schema = Array::new().items(RefOr::Type(Schema::object(
1079 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1080 )));
1081
1082 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1083 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1084 let json_de_str = serde_json::to_string(&deserialized).expect("");
1085 assert_eq!(json_str, json_de_str);
1086 }
1087
1088 #[test]
1089 fn serialize_deserialize_schema_with_additional_properties() {
1090 let schema = Schema::object(Object::new().property(
1091 "map",
1092 Object::new().additional_properties(AdditionalProperties::FreeForm(true)),
1093 ));
1094
1095 let json_str = serde_json::to_string(&schema).unwrap();
1096 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
1097 let json_de_str = serde_json::to_string(&deserialized).unwrap();
1098 assert_eq!(json_str, json_de_str);
1099 }
1100
1101 #[test]
1102 fn serialize_deserialize_schema_with_additional_properties_object() {
1103 let schema = Schema::object(Object::new().property(
1104 "map",
1105 Object::new().additional_properties(
1106 Object::new().property("name", Object::with_type(BasicType::String)),
1107 ),
1108 ));
1109
1110 let json_str = serde_json::to_string(&schema).expect("serde json should success");
1111 let deserialized: RefOr<Schema> =
1112 serde_json::from_str(&json_str).expect("serde json should success");
1113 let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
1114 assert_eq!(json_str, json_de_str);
1115 }
1116
1117 #[test]
1118 fn serialize_discriminator_with_mapping() {
1119 let mut discriminator = Discriminator::new("type");
1120 discriminator.mapping = [("int".to_owned(), "#/components/schemas/MyInt".to_owned())]
1121 .into_iter()
1122 .collect::<PropMap<_, _>>();
1123 let one_of = OneOf::new()
1124 .item(Ref::from_schema_name("MyInt"))
1125 .discriminator(discriminator);
1126 let json_value = serde_json::to_value(one_of).expect("serde json should success");
1127
1128 assert_json_eq!(
1129 json_value,
1130 json!({
1131 "oneOf": [
1132 {
1133 "$ref": "#/components/schemas/MyInt"
1134 }
1135 ],
1136 "discriminator": {
1137 "propertyName": "type",
1138 "mapping": {
1139 "int": "#/components/schemas/MyInt"
1140 }
1141 }
1142 })
1143 );
1144 }
1145
1146 #[test]
1147 fn deserialize_reserialize_one_of_default_type() {
1148 let a = OneOf::new()
1149 .item(Schema::Array(Array::new().items(RefOr::Type(
1150 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
1151 ))))
1152 .item(Schema::Array(Array::new().items(RefOr::Type(
1153 Schema::object(Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar")))),
1154 ))));
1155
1156 let serialized_json = serde_json::to_string(&a).expect("should serialize to json");
1157 let b: OneOf = serde_json::from_str(&serialized_json).expect("should deserialize OneOf");
1158 let reserialized_json = serde_json::to_string(&b).expect("reserialized json");
1159
1160 assert_eq!(serialized_json, reserialized_json);
1161 }
1162
1163 #[test]
1164 fn serialize_deserialize_object_with_multiple_schema_types() {
1165 let object =
1166 Object::new().schema_type(SchemaType::from_iter([BasicType::Object, BasicType::Null]));
1167
1168 let json_str = serde_json::to_string(&object).expect("serde json should success");
1169 let deserialized: Object =
1170 serde_json::from_str(&json_str).expect("serde json should success");
1171 let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
1172 assert_eq!(json_str, json_de_str);
1173 }
1174
1175 #[test]
1176 fn test_empty_schema() {
1177 let schema = empty();
1178 assert_json_eq!(
1179 schema,
1180 json!({
1181 "default": null
1182 })
1183 )
1184 }
1185
1186 #[test]
1187 fn test_default_schema() {
1188 let schema = Schema::default();
1189 assert_json_eq!(
1190 schema,
1191 json!({
1192 "type": "object",
1193 })
1194 )
1195 }
1196
1197 #[test]
1198 fn test_ref_from_response_name() {
1199 let _ref = Ref::from_response_name("MyResponse");
1200 assert_json_eq!(
1201 _ref,
1202 json!({
1203 "$ref": "#/components/responses/MyResponse"
1204 })
1205 )
1206 }
1207
1208 #[test]
1209 fn test_additional_properties_from_ref_or() {
1210 let additional_properties =
1211 AdditionalProperties::from(RefOr::Type(Schema::Object(Box::default())));
1212 assert_json_eq!(
1213 additional_properties,
1214 json!({
1215 "type": "object",
1216 })
1217 )
1218 }
1219}