1mod all_of;
6mod any_of;
7mod array;
8mod object;
9mod one_of;
10
11use std::ops::{Deref, DerefMut};
12
13pub use all_of::AllOf;
14pub use any_of::AnyOf;
15pub use array::Array;
16pub use object::Object;
17pub use one_of::OneOf;
18use serde::{Deserialize, Serialize};
19
20use crate::{PropMap, RefOr};
21
22#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
24#[serde(rename_all = "camelCase")]
25pub struct Schemas(pub PropMap<String, RefOr<Schema>>);
26
27impl<K, R> From<PropMap<K, R>> for Schemas
28where
29 K: Into<String>,
30 R: Into<RefOr<Schema>>,
31{
32 fn from(inner: PropMap<K, R>) -> Self {
33 Self(
34 inner
35 .into_iter()
36 .map(|(k, v)| (k.into(), v.into()))
37 .collect(),
38 )
39 }
40}
41impl<K, R, const N: usize> From<[(K, R); N]> for Schemas
42where
43 K: Into<String>,
44 R: Into<RefOr<Schema>>,
45{
46 fn from(inner: [(K, R); N]) -> Self {
47 Self(
48 <[(K, R)]>::into_vec(Box::new(inner))
49 .into_iter()
50 .map(|(k, v)| (k.into(), v.into()))
51 .collect(),
52 )
53 }
54}
55
56impl Deref for Schemas {
57 type Target = PropMap<String, RefOr<Schema>>;
58
59 fn deref(&self) -> &Self::Target {
60 &self.0
61 }
62}
63
64impl DerefMut for Schemas {
65 fn deref_mut(&mut self) -> &mut Self::Target {
66 &mut self.0
67 }
68}
69
70impl IntoIterator for Schemas {
71 type Item = (String, RefOr<Schema>);
72 type IntoIter = <PropMap<String, RefOr<Schema>> as IntoIterator>::IntoIter;
73
74 fn into_iter(self) -> Self::IntoIter {
75 self.0.into_iter()
76 }
77}
78
79impl Schemas {
80 #[must_use]
82 pub fn new() -> Self {
83 Default::default()
84 }
85 #[must_use]
87 pub fn schema<K: Into<String>, V: Into<RefOr<Schema>>>(mut self, key: K, value: V) -> Self {
88 self.insert(key, value);
89 self
90 }
91 pub fn insert<K: Into<String>, V: Into<RefOr<Schema>>>(&mut self, key: K, value: V) {
93 self.0.insert(key.into(), value.into());
94 }
95 pub fn append(&mut self, other: &mut Self) {
100 let items = std::mem::take(&mut other.0);
101 for item in items {
102 self.insert(item.0, item.1);
103 }
104 }
105 pub fn extend<I, K, V>(&mut self, iter: I)
107 where
108 I: IntoIterator<Item = (K, V)>,
109 K: Into<String>,
110 V: Into<RefOr<Schema>>,
111 {
112 for (k, v) in iter.into_iter() {
113 self.insert(k, v);
114 }
115 }
116}
117
118#[must_use]
123pub fn empty() -> Schema {
124 Schema::object(
125 Object::new()
126 .schema_type(SchemaType::AnyValue)
127 .default_value(serde_json::Value::Null),
128 )
129}
130
131#[non_exhaustive]
136#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
137#[serde(untagged, rename_all = "camelCase")]
138pub enum Schema {
139 Array(Array),
142 Object(Box<Object>),
145 OneOf(OneOf),
151
152 AllOf(AllOf),
156
157 AnyOf(AnyOf),
161}
162
163impl Default for Schema {
164 fn default() -> Self {
165 Self::Object(Default::default())
166 }
167}
168
169impl Schema {
170 #[must_use]
172 pub fn object(obj: Object) -> Self {
173 Self::Object(Box::new(obj))
174 }
175}
176
177#[non_exhaustive]
182#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
183#[serde(rename_all = "camelCase")]
184pub struct Discriminator {
185 pub property_name: String,
188
189 #[serde(skip_serializing_if = "PropMap::is_empty", default)]
193 pub mapping: PropMap<String, String>,
194}
195
196impl Discriminator {
197 pub fn new<I: Into<String>>(property_name: I) -> Self {
207 Self {
208 property_name: property_name.into(),
209 mapping: PropMap::new(),
210 }
211 }
212}
213
214#[allow(clippy::trivially_copy_pass_by_ref)]
215fn is_false(value: &bool) -> bool {
216 !*value
217}
218
219#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
223#[serde(untagged)]
224pub enum AdditionalProperties<T> {
225 RefOr(RefOr<T>),
227 FreeForm(bool),
229}
230
231impl<T> From<RefOr<T>> for AdditionalProperties<T> {
232 fn from(value: RefOr<T>) -> Self {
233 Self::RefOr(value)
234 }
235}
236
237impl From<Object> for AdditionalProperties<Schema> {
238 fn from(value: Object) -> Self {
239 Self::RefOr(RefOr::Type(Schema::object(value)))
240 }
241}
242
243impl From<Array> for AdditionalProperties<Schema> {
244 fn from(value: Array) -> Self {
245 Self::RefOr(RefOr::Type(Schema::Array(value)))
246 }
247}
248
249impl From<Ref> for AdditionalProperties<Schema> {
250 fn from(value: Ref) -> Self {
251 Self::RefOr(RefOr::Ref(value))
252 }
253}
254
255#[non_exhaustive]
260#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
261pub struct Ref {
262 #[serde(rename = "$ref")]
264 pub ref_location: String,
265
266 #[serde(skip_serializing_if = "String::is_empty", default)]
270 pub description: String,
271
272 #[serde(skip_serializing_if = "String::is_empty", default)]
275 pub summary: String,
276}
277
278impl Ref {
279 #[must_use]
282 pub fn new<I: Into<String>>(ref_location: I) -> Self {
283 Self {
284 ref_location: ref_location.into(),
285 ..Default::default()
286 }
287 }
288
289 #[must_use]
292 pub fn from_schema_name<I: Into<String>>(schema_name: I) -> Self {
293 Self::new(format!("#/components/schemas/{}", schema_name.into()))
294 }
295
296 #[must_use]
299 pub fn from_response_name<I: Into<String>>(response_name: I) -> Self {
300 Self::new(format!("#/components/responses/{}", response_name.into()))
301 }
302
303 #[must_use]
305 pub fn ref_location(mut self, ref_location: String) -> Self {
306 self.ref_location = ref_location;
307 self
308 }
309
310 #[must_use]
313 pub fn ref_location_from_schema_name<S: Into<String>>(mut self, schema_name: S) -> Self {
314 self.ref_location = format!("#/components/schemas/{}", schema_name.into());
315 self
316 }
317
318 #[must_use]
324 pub fn description<S: Into<String>>(mut self, description: S) -> Self {
325 self.description = description.into();
326 self
327 }
328
329 #[must_use]
333 pub fn summary<S: Into<String>>(mut self, summary: S) -> Self {
334 self.summary = summary.into();
335 self
336 }
337
338 #[must_use]
340 pub fn to_array(self) -> Array {
341 Array::new().items(self)
342 }
343}
344
345impl From<Ref> for RefOr<Schema> {
346 fn from(r: Ref) -> Self {
347 Self::Ref(r)
348 }
349}
350
351impl<T> From<T> for RefOr<T> {
352 fn from(t: T) -> Self {
353 Self::Type(t)
354 }
355}
356
357impl Default for RefOr<Schema> {
358 fn default() -> Self {
359 Self::Type(Schema::object(Object::new()))
360 }
361}
362
363#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
367#[serde(untagged)]
368pub enum SchemaType {
369 Basic(BasicType),
371 Array(Vec<BasicType>),
373 AnyValue,
376}
377
378impl Default for SchemaType {
379 fn default() -> Self {
380 Self::Basic(BasicType::default())
381 }
382}
383
384impl From<BasicType> for SchemaType {
385 fn from(value: BasicType) -> Self {
386 Self::basic(value)
387 }
388}
389
390impl FromIterator<BasicType> for SchemaType {
391 fn from_iter<T: IntoIterator<Item = BasicType>>(iter: T) -> Self {
392 Self::Array(iter.into_iter().collect())
393 }
394}
395impl SchemaType {
396 #[must_use]
408 pub fn basic(r#type: BasicType) -> Self {
409 Self::Basic(r#type)
410 }
411
412 #[must_use]
416 pub fn any() -> Self {
417 Self::AnyValue
418 }
419
420 #[must_use]
423 pub fn is_any_value(&self) -> bool {
424 matches!(self, Self::AnyValue)
425 }
426}
427
428#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
448#[serde(rename_all = "lowercase")]
449pub enum BasicType {
450 #[default]
452 Object,
453 String,
456 Integer,
459 Number,
462 Boolean,
465 Array,
467 Null,
469}
470
471#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
477#[serde(rename_all = "lowercase", untagged)]
478pub enum SchemaFormat {
479 KnownFormat(KnownFormat),
481 Custom(String),
484}
485
486#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
492#[serde(rename_all = "kebab-case")]
493pub enum KnownFormat {
494 Int8,
496 Int16,
498 Int32,
500 Int64,
502 #[serde(rename = "uint8")]
504 UInt8,
505 #[serde(rename = "uint16")]
507 UInt16,
508 #[serde(rename = "uint32")]
510 UInt32,
511 #[serde(rename = "uint64")]
513 UInt64,
514 Float,
516 Double,
518 Byte,
520 Binary,
522 Time,
524 Date,
526 DateTime,
528 Duration,
530 Password,
532 String,
534 #[cfg(any(feature = "decimal", feature = "decimal-float"))]
538 #[cfg_attr(docsrs, doc(cfg(any(feature = "decimal", feature = "decimal-float"))))]
539 Decimal,
540 #[cfg(feature = "ulid")]
542 #[cfg_attr(docsrs, doc(cfg(feature = "ulid")))]
543 Ulid,
544
545 #[cfg(feature = "uuid")]
547 #[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
548 Uuid,
549 #[cfg(feature = "url")]
553 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
554 Url,
555 #[cfg(feature = "url")]
559 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
560 UriReference,
561 #[cfg(feature = "url")]
564 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
565 Iri,
566 #[cfg(feature = "url")]
570 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
571 IriReference,
572 Email,
574 IdnEmail,
576 Hostname,
580 IdnHostname,
583 Ipv4,
585 Ipv6,
587 UriTemplate,
592 JsonPointer,
594 RelativeJsonPointer,
596 Regex,
599}
600
601#[cfg(test)]
602mod tests {
603 use assert_json_diff::assert_json_eq;
604 use serde_json::{Value, json};
605
606 use super::*;
607 use crate::*;
608
609 #[test]
610 fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
611 let openapi = OpenApi::new("My api", "1.0.0").components(
612 Components::new()
613 .add_schema("Person", Ref::new("#/components/PersonModel"))
614 .add_schema(
615 "Credential",
616 Schema::from(
617 Object::new()
618 .property(
619 "id",
620 Object::new()
621 .schema_type(BasicType::Integer)
622 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
623 .description("Id of credential")
624 .default_value(json!(1i32)),
625 )
626 .property(
627 "name",
628 Object::new()
629 .schema_type(BasicType::String)
630 .description("Name of credential"),
631 )
632 .property(
633 "status",
634 Object::new()
635 .schema_type(BasicType::String)
636 .default_value(json!("Active"))
637 .description("Credential status")
638 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
639 )
640 .property(
641 "history",
642 Array::new().items(Ref::from_schema_name("UpdateHistory")),
643 )
644 .property("tags", Object::with_type(BasicType::String).to_array()),
645 ),
646 ),
647 );
648
649 let serialized = serde_json::to_string_pretty(&openapi)?;
650 println!("serialized json:\n {serialized}");
651
652 let value = serde_json::to_value(&openapi)?;
653 let credential = get_json_path(&value, "components.schemas.Credential.properties");
654 let person = get_json_path(&value, "components.schemas.Person");
655
656 assert!(
657 credential.get("id").is_some(),
658 "could not find path: components.schemas.Credential.properties.id"
659 );
660 assert!(
661 credential.get("status").is_some(),
662 "could not find path: components.schemas.Credential.properties.status"
663 );
664 assert!(
665 credential.get("name").is_some(),
666 "could not find path: components.schemas.Credential.properties.name"
667 );
668 assert!(
669 credential.get("history").is_some(),
670 "could not find path: components.schemas.Credential.properties.history"
671 );
672 assert_json_eq!(
673 credential
674 .get("id")
675 .unwrap_or(&serde_json::value::Value::Null),
676 json!({"type":"integer","format":"int32","description":"Id of credential","default":1})
677 );
678 assert_json_eq!(
679 credential
680 .get("name")
681 .unwrap_or(&serde_json::value::Value::Null),
682 json!({"type":"string","description":"Name of credential"})
683 );
684 assert_json_eq!(
685 credential
686 .get("status")
687 .unwrap_or(&serde_json::value::Value::Null),
688 json!({"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"})
689 );
690 assert_json_eq!(
691 credential
692 .get("history")
693 .unwrap_or(&serde_json::value::Value::Null),
694 json!({"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"})
695 );
696 assert_eq!(person, &json!({"$ref":"#/components/PersonModel"}));
697
698 Ok(())
699 }
700
701 #[test]
703 fn test_property_order() {
704 let json_value = Object::new()
705 .property(
706 "id",
707 Object::new()
708 .schema_type(BasicType::Integer)
709 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
710 .description("Id of credential")
711 .default_value(json!(1i32)),
712 )
713 .property(
714 "name",
715 Object::new()
716 .schema_type(BasicType::String)
717 .description("Name of credential"),
718 )
719 .property(
720 "status",
721 Object::new()
722 .schema_type(BasicType::String)
723 .default_value(json!("Active"))
724 .description("Credential status")
725 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
726 )
727 .property(
728 "history",
729 Array::new().items(Ref::from_schema_name("UpdateHistory")),
730 )
731 .property("tags", Object::with_type(BasicType::String).to_array());
732
733 #[cfg(not(feature = "preserve-order"))]
734 assert_eq!(
735 json_value.properties.keys().collect::<Vec<_>>(),
736 vec!["history", "id", "name", "status", "tags"]
737 );
738
739 #[cfg(feature = "preserve-order")]
740 assert_eq!(
741 json_value.properties.keys().collect::<Vec<_>>(),
742 vec!["id", "name", "status", "history", "tags"]
743 );
744 }
745
746 #[test]
748 fn test_additional_properties() {
749 let json_value =
750 Object::new().additional_properties(Object::new().schema_type(BasicType::String));
751 assert_json_eq!(
752 json_value,
753 json!({
754 "type": "object",
755 "additionalProperties": {
756 "type": "string"
757 }
758 })
759 );
760
761 let json_value = Object::new().additional_properties(
762 Array::new().items(Object::new().schema_type(BasicType::Number)),
763 );
764 assert_json_eq!(
765 json_value,
766 json!({
767 "type": "object",
768 "additionalProperties": {
769 "items": {
770 "type": "number",
771 },
772 "type": "array",
773 }
774 })
775 );
776
777 let json_value = Object::new().additional_properties(Ref::from_schema_name("ComplexModel"));
778 assert_json_eq!(
779 json_value,
780 json!({
781 "type": "object",
782 "additionalProperties": {
783 "$ref": "#/components/schemas/ComplexModel"
784 }
785 })
786 )
787 }
788
789 #[test]
790 fn test_object_with_name() {
791 let json_value = Object::new().name("SomeName");
792 assert_json_eq!(
793 json_value,
794 json!({
795 "type": "object",
796 "name": "SomeName"
797 })
798 );
799 }
800
801 #[test]
802 fn test_derive_object_with_examples() {
803 let expected = r#"{"type":"object","examples":[{"age":20,"name":"bob the cat"}]}"#;
804 let json_value = Object::new().examples([json!({"age": 20, "name": "bob the cat"})]);
805
806 let value_string = serde_json::to_string(&json_value).unwrap();
807 assert_eq!(
808 value_string, expected,
809 "value string != expected string, {value_string} != {expected}"
810 );
811 }
812
813 fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
814 path.split('.').fold(value, |acc, fragment| {
815 acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
816 })
817 }
818
819 #[test]
820 fn test_array_new() {
821 let array = Array::new().items(
822 Object::new().property(
823 "id",
824 Object::new()
825 .schema_type(BasicType::Integer)
826 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
827 .description("Id of credential")
828 .default_value(json!(1i32)),
829 ),
830 );
831
832 assert!(matches!(
833 array.schema_type,
834 SchemaType::Basic(BasicType::Array)
835 ));
836 }
837
838 #[test]
839 fn test_array_builder() {
840 let array: Array = Array::new().items(
841 Object::new().property(
842 "id",
843 Object::new()
844 .schema_type(BasicType::Integer)
845 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
846 .description("Id of credential")
847 .default_value(json!(1i32)),
848 ),
849 );
850
851 assert!(matches!(
852 array.schema_type,
853 SchemaType::Basic(BasicType::Array)
854 ));
855 }
856
857 #[test]
858 fn reserialize_deserialized_schema_components() {
859 let components = Components::new()
860 .extend_schemas(vec![(
861 "Comp",
862 Schema::from(
863 Object::new()
864 .property("name", Object::new().schema_type(BasicType::String))
865 .required("name"),
866 ),
867 )])
868 .response("204", Response::new("No Content"))
869 .extend_responses(vec![("200", Response::new("Okay"))])
870 .add_security_scheme("TLS", SecurityScheme::MutualTls { description: None })
871 .extend_security_schemes(vec![(
872 "APIKey",
873 SecurityScheme::Http(security::Http::default()),
874 )]);
875
876 let serialized_components = serde_json::to_string(&components).unwrap();
877
878 let deserialized_components: Components =
879 serde_json::from_str(serialized_components.as_str()).unwrap();
880
881 assert_eq!(
882 serialized_components,
883 serde_json::to_string(&deserialized_components).unwrap()
884 )
885 }
886
887 #[test]
888 fn reserialize_deserialized_object_component() {
889 let prop = Object::new()
890 .property("name", Object::new().schema_type(BasicType::String))
891 .required("name");
892
893 let serialized_components = serde_json::to_string(&prop).unwrap();
894 let deserialized_components: Object =
895 serde_json::from_str(serialized_components.as_str()).unwrap();
896
897 assert_eq!(
898 serialized_components,
899 serde_json::to_string(&deserialized_components).unwrap()
900 )
901 }
902
903 #[test]
904 fn reserialize_deserialized_property() {
905 let prop = Object::new().schema_type(BasicType::String);
906
907 let serialized_components = serde_json::to_string(&prop).unwrap();
908 let deserialized_components: Object =
909 serde_json::from_str(serialized_components.as_str()).unwrap();
910
911 assert_eq!(
912 serialized_components,
913 serde_json::to_string(&deserialized_components).unwrap()
914 )
915 }
916
917 #[test]
918 fn serialize_deserialize_array_within_ref_or_t_object_builder() {
919 let ref_or_schema = RefOr::Type(Schema::object(Object::new().property(
920 "test",
921 RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
922 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
923 )))),
924 )));
925
926 let json_str = serde_json::to_string(&ref_or_schema).expect("");
927 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
928 let json_de_str = serde_json::to_string(&deserialized).expect("");
929 assert_eq!(json_str, json_de_str);
930 }
931
932 #[test]
933 fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
934 let ref_or_schema = RefOr::Type(Schema::object(
935 Object::new().property(
936 "test",
937 RefOr::Type(Schema::OneOf(
938 OneOf::new()
939 .item(Schema::Array(Array::new().items(RefOr::Type(
940 Schema::object(
941 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
942 ),
943 ))))
944 .item(Schema::Array(Array::new().items(RefOr::Type(
945 Schema::object(
946 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
947 ),
948 )))),
949 )),
950 ),
951 ));
952
953 let json_str = serde_json::to_string(&ref_or_schema).expect("");
954 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
955 let json_de_str = serde_json::to_string(&deserialized).expect("");
956 assert_eq!(json_str, json_de_str);
957 }
958
959 #[test]
960 fn serialize_deserialize_all_of_of_within_ref_or_t_object() {
961 let ref_or_schema = RefOr::Type(Schema::object(
962 Object::new().property(
963 "test",
964 RefOr::Type(Schema::AllOf(
965 AllOf::new()
966 .item(Schema::Array(Array::new().items(RefOr::Type(
967 Schema::object(
968 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
969 ),
970 ))))
971 .item(RefOr::Type(Schema::object(
972 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
973 ))),
974 )),
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_any_of_of_within_ref_or_t_object() {
986 let ref_or_schema = RefOr::Type(Schema::object(
987 Object::new().property(
988 "test",
989 RefOr::Type(Schema::AnyOf(
990 AnyOf::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(RefOr::Type(Schema::object(
997 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
998 ))),
999 )),
1000 ),
1001 ));
1002
1003 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1004 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1005 let json_de_str = serde_json::to_string(&deserialized).expect("");
1006 assert!(json_str.contains("\"anyOf\""));
1007 assert_eq!(json_str, json_de_str);
1008 }
1009
1010 #[test]
1011 fn serialize_deserialize_schema_array_ref_or_t() {
1012 let ref_or_schema = RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
1013 Schema::Object(Box::new(
1014 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1015 )),
1016 ))));
1017
1018 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1019 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1020 let json_de_str = serde_json::to_string(&deserialized).expect("");
1021 assert_eq!(json_str, json_de_str);
1022 }
1023
1024 #[test]
1025 fn serialize_deserialize_schema_array() {
1026 let ref_or_schema = Array::new().items(RefOr::Type(Schema::object(
1027 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
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_schema_with_additional_properties() {
1038 let schema = Schema::object(Object::new().property(
1039 "map",
1040 Object::new().additional_properties(AdditionalProperties::FreeForm(true)),
1041 ));
1042
1043 let json_str = serde_json::to_string(&schema).unwrap();
1044 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
1045 let json_de_str = serde_json::to_string(&deserialized).unwrap();
1046 assert_eq!(json_str, json_de_str);
1047 }
1048
1049 #[test]
1050 fn serialize_deserialize_schema_with_additional_properties_object() {
1051 let schema = Schema::object(Object::new().property(
1052 "map",
1053 Object::new().additional_properties(
1054 Object::new().property("name", Object::with_type(BasicType::String)),
1055 ),
1056 ));
1057
1058 let json_str = serde_json::to_string(&schema).expect("serde json should success");
1059 let deserialized: RefOr<Schema> =
1060 serde_json::from_str(&json_str).expect("serde json should success");
1061 let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
1062 assert_eq!(json_str, json_de_str);
1063 }
1064
1065 #[test]
1066 fn serialize_discriminator_with_mapping() {
1067 let mut discriminator = Discriminator::new("type");
1068 discriminator.mapping = [("int".to_owned(), "#/components/schemas/MyInt".to_owned())]
1069 .into_iter()
1070 .collect::<PropMap<_, _>>();
1071 let one_of = OneOf::new()
1072 .item(Ref::from_schema_name("MyInt"))
1073 .discriminator(discriminator);
1074 let json_value = serde_json::to_value(one_of).expect("serde json should success");
1075
1076 assert_json_eq!(
1077 json_value,
1078 json!({
1079 "oneOf": [
1080 {
1081 "$ref": "#/components/schemas/MyInt"
1082 }
1083 ],
1084 "discriminator": {
1085 "propertyName": "type",
1086 "mapping": {
1087 "int": "#/components/schemas/MyInt"
1088 }
1089 }
1090 })
1091 );
1092 }
1093
1094 #[test]
1095 fn deserialize_reserialize_one_of_default_type() {
1096 let a = OneOf::new()
1097 .item(Schema::Array(Array::new().items(RefOr::Type(
1098 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
1099 ))))
1100 .item(Schema::Array(Array::new().items(RefOr::Type(
1101 Schema::object(Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar")))),
1102 ))));
1103
1104 let serialized_json = serde_json::to_string(&a).expect("should serialize to json");
1105 let b: OneOf = serde_json::from_str(&serialized_json).expect("should deserialize OneOf");
1106 let reserialized_json = serde_json::to_string(&b).expect("reserialized json");
1107
1108 assert_eq!(serialized_json, reserialized_json);
1109 }
1110
1111 #[test]
1112 fn serialize_deserialize_object_with_multiple_schema_types() {
1113 let object =
1114 Object::new().schema_type(SchemaType::from_iter([BasicType::Object, BasicType::Null]));
1115
1116 let json_str = serde_json::to_string(&object).expect("serde json should success");
1117 let deserialized: Object =
1118 serde_json::from_str(&json_str).expect("serde json should success");
1119 let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
1120 assert_eq!(json_str, json_de_str);
1121 }
1122
1123 #[test]
1124 fn test_empty_schema() {
1125 let schema = empty();
1126 assert_json_eq!(
1127 schema,
1128 json!({
1129 "default": null
1130 })
1131 )
1132 }
1133
1134 #[test]
1135 fn test_default_schema() {
1136 let schema = Schema::default();
1137 assert_json_eq!(
1138 schema,
1139 json!({
1140 "type": "object",
1141 })
1142 )
1143 }
1144
1145 #[test]
1146 fn test_ref_from_response_name() {
1147 let _ref = Ref::from_response_name("MyResponse");
1148 assert_json_eq!(
1149 _ref,
1150 json!({
1151 "$ref": "#/components/responses/MyResponse"
1152 })
1153 )
1154 }
1155
1156 #[test]
1157 fn test_additional_properties_from_ref_or() {
1158 let additional_properties =
1159 AdditionalProperties::from(RefOr::Type(Schema::Object(Box::default())));
1160 assert_json_eq!(
1161 additional_properties,
1162 json!({
1163 "type": "object",
1164 })
1165 )
1166 }
1167}