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