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;
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 #[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]
417 pub fn any() -> Self {
418 Self::AnyValue
419 }
420
421 #[must_use]
424 pub fn is_any_value(&self) -> bool {
425 matches!(self, Self::AnyValue)
426 }
427}
428
429#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
449#[serde(rename_all = "lowercase")]
450pub enum BasicType {
451 #[default]
453 Object,
454 String,
457 Integer,
460 Number,
463 Boolean,
466 Array,
468 Null,
470}
471
472#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
478#[serde(rename_all = "lowercase", untagged)]
479pub enum SchemaFormat {
480 KnownFormat(KnownFormat),
482 Custom(String),
485}
486
487#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
493#[serde(rename_all = "kebab-case")]
494pub enum KnownFormat {
495 Int8,
497 Int16,
499 Int32,
501 Int64,
503 #[serde(rename = "uint8")]
505 UInt8,
506 #[serde(rename = "uint16")]
508 UInt16,
509 #[serde(rename = "uint32")]
511 UInt32,
512 #[serde(rename = "uint64")]
514 UInt64,
515 Float,
517 Double,
519 Byte,
521 Binary,
523 Time,
525 Date,
527 DateTime,
529 Duration,
531 Password,
533 String,
535 #[cfg(any(feature = "decimal", feature = "decimal-float"))]
539 #[cfg_attr(docsrs, doc(cfg(any(feature = "decimal", feature = "decimal-float"))))]
540 Decimal,
541 #[cfg(feature = "ulid")]
543 #[cfg_attr(docsrs, doc(cfg(feature = "ulid")))]
544 Ulid,
545
546 #[cfg(feature = "uuid")]
548 #[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
549 Uuid,
550 #[cfg(feature = "url")]
554 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
555 Url,
556 #[cfg(feature = "url")]
560 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
561 UriReference,
562 #[cfg(feature = "url")]
565 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
566 Iri,
567 #[cfg(feature = "url")]
571 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
572 IriReference,
573 Email,
575 IdnEmail,
577 Hostname,
581 IdnHostname,
584 Ipv4,
586 Ipv6,
588 UriTemplate,
593 JsonPointer,
595 RelativeJsonPointer,
597 Regex,
600}
601
602#[cfg(test)]
603mod tests {
604 use assert_json_diff::assert_json_eq;
605 use serde_json::{Value, json};
606
607 use super::*;
608 use crate::*;
609
610 #[test]
611 fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
612 let openapi = OpenApi::new("My api", "1.0.0").components(
613 Components::new()
614 .add_schema("Person", Ref::new("#/components/PersonModel"))
615 .add_schema(
616 "Credential",
617 Schema::from(
618 Object::new()
619 .property(
620 "id",
621 Object::new()
622 .schema_type(BasicType::Integer)
623 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
624 .description("Id of credential")
625 .default_value(json!(1i32)),
626 )
627 .property(
628 "name",
629 Object::new()
630 .schema_type(BasicType::String)
631 .description("Name of credential"),
632 )
633 .property(
634 "status",
635 Object::new()
636 .schema_type(BasicType::String)
637 .default_value(json!("Active"))
638 .description("Credential status")
639 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
640 )
641 .property(
642 "history",
643 Array::new().items(Ref::from_schema_name("UpdateHistory")),
644 )
645 .property("tags", Object::with_type(BasicType::String).to_array()),
646 ),
647 ),
648 );
649
650 let serialized = serde_json::to_string_pretty(&openapi)?;
651 println!("serialized json:\n {serialized}");
652
653 let value = serde_json::to_value(&openapi)?;
654 let credential = get_json_path(&value, "components.schemas.Credential.properties");
655 let person = get_json_path(&value, "components.schemas.Person");
656
657 assert!(
658 credential.get("id").is_some(),
659 "could not find path: components.schemas.Credential.properties.id"
660 );
661 assert!(
662 credential.get("status").is_some(),
663 "could not find path: components.schemas.Credential.properties.status"
664 );
665 assert!(
666 credential.get("name").is_some(),
667 "could not find path: components.schemas.Credential.properties.name"
668 );
669 assert!(
670 credential.get("history").is_some(),
671 "could not find path: components.schemas.Credential.properties.history"
672 );
673 assert_json_eq!(
674 credential
675 .get("id")
676 .unwrap_or(&serde_json::value::Value::Null),
677 json!({"type":"integer","format":"int32","description":"Id of credential","default":1})
678 );
679 assert_json_eq!(
680 credential
681 .get("name")
682 .unwrap_or(&serde_json::value::Value::Null),
683 json!({"type":"string","description":"Name of credential"})
684 );
685 assert_json_eq!(
686 credential
687 .get("status")
688 .unwrap_or(&serde_json::value::Value::Null),
689 json!({"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"})
690 );
691 assert_json_eq!(
692 credential
693 .get("history")
694 .unwrap_or(&serde_json::value::Value::Null),
695 json!({"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"})
696 );
697 assert_eq!(person, &json!({"$ref":"#/components/PersonModel"}));
698
699 Ok(())
700 }
701
702 #[test]
704 fn test_property_order() {
705 let json_value = Object::new()
706 .property(
707 "id",
708 Object::new()
709 .schema_type(BasicType::Integer)
710 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
711 .description("Id of credential")
712 .default_value(json!(1i32)),
713 )
714 .property(
715 "name",
716 Object::new()
717 .schema_type(BasicType::String)
718 .description("Name of credential"),
719 )
720 .property(
721 "status",
722 Object::new()
723 .schema_type(BasicType::String)
724 .default_value(json!("Active"))
725 .description("Credential status")
726 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
727 )
728 .property(
729 "history",
730 Array::new().items(Ref::from_schema_name("UpdateHistory")),
731 )
732 .property("tags", Object::with_type(BasicType::String).to_array());
733
734 #[cfg(not(feature = "preserve-order"))]
735 assert_eq!(
736 json_value.properties.keys().collect::<Vec<_>>(),
737 vec!["history", "id", "name", "status", "tags"]
738 );
739
740 #[cfg(feature = "preserve-order")]
741 assert_eq!(
742 json_value.properties.keys().collect::<Vec<_>>(),
743 vec!["id", "name", "status", "history", "tags"]
744 );
745 }
746
747 #[test]
749 fn test_additional_properties() {
750 let json_value =
751 Object::new().additional_properties(Object::new().schema_type(BasicType::String));
752 assert_json_eq!(
753 json_value,
754 json!({
755 "type": "object",
756 "additionalProperties": {
757 "type": "string"
758 }
759 })
760 );
761
762 let json_value = Object::new().additional_properties(
763 Array::new().items(Object::new().schema_type(BasicType::Number)),
764 );
765 assert_json_eq!(
766 json_value,
767 json!({
768 "type": "object",
769 "additionalProperties": {
770 "items": {
771 "type": "number",
772 },
773 "type": "array",
774 }
775 })
776 );
777
778 let json_value = Object::new().additional_properties(Ref::from_schema_name("ComplexModel"));
779 assert_json_eq!(
780 json_value,
781 json!({
782 "type": "object",
783 "additionalProperties": {
784 "$ref": "#/components/schemas/ComplexModel"
785 }
786 })
787 )
788 }
789
790 #[test]
791 fn test_object_with_name() {
792 let json_value = Object::new().name("SomeName");
793 assert_json_eq!(
794 json_value,
795 json!({
796 "type": "object",
797 "name": "SomeName"
798 })
799 );
800 }
801
802 #[test]
803 fn test_derive_object_with_examples() {
804 let expected = r#"{"type":"object","examples":[{"age":20,"name":"bob the cat"}]}"#;
805 let json_value = Object::new().examples([json!({"age": 20, "name": "bob the cat"})]);
806
807 let value_string = serde_json::to_string(&json_value).unwrap();
808 assert_eq!(
809 value_string, expected,
810 "value string != expected string, {value_string} != {expected}"
811 );
812 }
813
814 fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
815 path.split('.').fold(value, |acc, fragment| {
816 acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
817 })
818 }
819
820 #[test]
821 fn test_array_new() {
822 let array = Array::new().items(
823 Object::new().property(
824 "id",
825 Object::new()
826 .schema_type(BasicType::Integer)
827 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
828 .description("Id of credential")
829 .default_value(json!(1i32)),
830 ),
831 );
832
833 assert!(matches!(
834 array.schema_type,
835 SchemaType::Basic(BasicType::Array)
836 ));
837 }
838
839 #[test]
840 fn test_array_builder() {
841 let array: Array = Array::new().items(
842 Object::new().property(
843 "id",
844 Object::new()
845 .schema_type(BasicType::Integer)
846 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
847 .description("Id of credential")
848 .default_value(json!(1i32)),
849 ),
850 );
851
852 assert!(matches!(
853 array.schema_type,
854 SchemaType::Basic(BasicType::Array)
855 ));
856 }
857
858 #[test]
859 fn reserialize_deserialized_schema_components() {
860 let components = Components::new()
861 .extend_schemas(vec![(
862 "Comp",
863 Schema::from(
864 Object::new()
865 .property("name", Object::new().schema_type(BasicType::String))
866 .required("name"),
867 ),
868 )])
869 .response("204", Response::new("No Content"))
870 .extend_responses(vec![("200", Response::new("Okay"))])
871 .add_security_scheme("TLS", SecurityScheme::MutualTls { description: None })
872 .extend_security_schemes(vec![(
873 "APIKey",
874 SecurityScheme::Http(security::Http::default()),
875 )]);
876
877 let serialized_components = serde_json::to_string(&components).unwrap();
878
879 let deserialized_components: Components =
880 serde_json::from_str(serialized_components.as_str()).unwrap();
881
882 assert_eq!(
883 serialized_components,
884 serde_json::to_string(&deserialized_components).unwrap()
885 )
886 }
887
888 #[test]
889 fn reserialize_deserialized_object_component() {
890 let prop = Object::new()
891 .property("name", Object::new().schema_type(BasicType::String))
892 .required("name");
893
894 let serialized_components = serde_json::to_string(&prop).unwrap();
895 let deserialized_components: Object =
896 serde_json::from_str(serialized_components.as_str()).unwrap();
897
898 assert_eq!(
899 serialized_components,
900 serde_json::to_string(&deserialized_components).unwrap()
901 )
902 }
903
904 #[test]
905 fn reserialize_deserialized_property() {
906 let prop = Object::new().schema_type(BasicType::String);
907
908 let serialized_components = serde_json::to_string(&prop).unwrap();
909 let deserialized_components: Object =
910 serde_json::from_str(serialized_components.as_str()).unwrap();
911
912 assert_eq!(
913 serialized_components,
914 serde_json::to_string(&deserialized_components).unwrap()
915 )
916 }
917
918 #[test]
919 fn serialize_deserialize_array_within_ref_or_t_object_builder() {
920 let ref_or_schema = RefOr::Type(Schema::object(Object::new().property(
921 "test",
922 RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
923 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
924 )))),
925 )));
926
927 let json_str = serde_json::to_string(&ref_or_schema).expect("");
928 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
929 let json_de_str = serde_json::to_string(&deserialized).expect("");
930 assert_eq!(json_str, json_de_str);
931 }
932
933 #[test]
934 fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
935 let ref_or_schema = RefOr::Type(Schema::object(
936 Object::new().property(
937 "test",
938 RefOr::Type(Schema::OneOf(
939 OneOf::new()
940 .item(Schema::Array(Array::new().items(RefOr::Type(
941 Schema::object(
942 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
943 ),
944 ))))
945 .item(Schema::Array(Array::new().items(RefOr::Type(
946 Schema::object(
947 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
948 ),
949 )))),
950 )),
951 ),
952 ));
953
954 let json_str = serde_json::to_string(&ref_or_schema).expect("");
955 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
956 let json_de_str = serde_json::to_string(&deserialized).expect("");
957 assert_eq!(json_str, json_de_str);
958 }
959
960 #[test]
961 fn serialize_deserialize_all_of_of_within_ref_or_t_object() {
962 let ref_or_schema = RefOr::Type(Schema::object(
963 Object::new().property(
964 "test",
965 RefOr::Type(Schema::AllOf(
966 AllOf::new()
967 .item(Schema::Array(Array::new().items(RefOr::Type(
968 Schema::object(
969 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
970 ),
971 ))))
972 .item(RefOr::Type(Schema::object(
973 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
974 ))),
975 )),
976 ),
977 ));
978
979 let json_str = serde_json::to_string(&ref_or_schema).expect("");
980 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
981 let json_de_str = serde_json::to_string(&deserialized).expect("");
982 assert_eq!(json_str, json_de_str);
983 }
984
985 #[test]
986 fn serialize_deserialize_any_of_of_within_ref_or_t_object() {
987 let ref_or_schema = RefOr::Type(Schema::object(
988 Object::new().property(
989 "test",
990 RefOr::Type(Schema::AnyOf(
991 AnyOf::new()
992 .item(Schema::Array(Array::new().items(RefOr::Type(
993 Schema::object(
994 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
995 ),
996 ))))
997 .item(RefOr::Type(Schema::object(
998 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
999 ))),
1000 )),
1001 ),
1002 ));
1003
1004 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1005 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1006 let json_de_str = serde_json::to_string(&deserialized).expect("");
1007 assert!(json_str.contains("\"anyOf\""));
1008 assert_eq!(json_str, json_de_str);
1009 }
1010
1011 #[test]
1012 fn serialize_deserialize_schema_array_ref_or_t() {
1013 let ref_or_schema = RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
1014 Schema::Object(Box::new(
1015 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1016 )),
1017 ))));
1018
1019 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1020 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1021 let json_de_str = serde_json::to_string(&deserialized).expect("");
1022 assert_eq!(json_str, json_de_str);
1023 }
1024
1025 #[test]
1026 fn serialize_deserialize_schema_array() {
1027 let ref_or_schema = Array::new().items(RefOr::Type(Schema::object(
1028 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1029 )));
1030
1031 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1032 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1033 let json_de_str = serde_json::to_string(&deserialized).expect("");
1034 assert_eq!(json_str, json_de_str);
1035 }
1036
1037 #[test]
1038 fn serialize_deserialize_schema_with_additional_properties() {
1039 let schema = Schema::object(Object::new().property(
1040 "map",
1041 Object::new().additional_properties(AdditionalProperties::FreeForm(true)),
1042 ));
1043
1044 let json_str = serde_json::to_string(&schema).unwrap();
1045 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
1046 let json_de_str = serde_json::to_string(&deserialized).unwrap();
1047 assert_eq!(json_str, json_de_str);
1048 }
1049
1050 #[test]
1051 fn serialize_deserialize_schema_with_additional_properties_object() {
1052 let schema = Schema::object(Object::new().property(
1053 "map",
1054 Object::new().additional_properties(
1055 Object::new().property("name", Object::with_type(BasicType::String)),
1056 ),
1057 ));
1058
1059 let json_str = serde_json::to_string(&schema).expect("serde json should success");
1060 let deserialized: RefOr<Schema> =
1061 serde_json::from_str(&json_str).expect("serde json should success");
1062 let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
1063 assert_eq!(json_str, json_de_str);
1064 }
1065
1066 #[test]
1067 fn serialize_discriminator_with_mapping() {
1068 let mut discriminator = Discriminator::new("type");
1069 discriminator.mapping = [("int".to_owned(), "#/components/schemas/MyInt".to_owned())]
1070 .into_iter()
1071 .collect::<PropMap<_, _>>();
1072 let one_of = OneOf::new()
1073 .item(Ref::from_schema_name("MyInt"))
1074 .discriminator(discriminator);
1075 let json_value = serde_json::to_value(one_of).expect("serde json should success");
1076
1077 assert_json_eq!(
1078 json_value,
1079 json!({
1080 "oneOf": [
1081 {
1082 "$ref": "#/components/schemas/MyInt"
1083 }
1084 ],
1085 "discriminator": {
1086 "propertyName": "type",
1087 "mapping": {
1088 "int": "#/components/schemas/MyInt"
1089 }
1090 }
1091 })
1092 );
1093 }
1094
1095 #[test]
1096 fn deserialize_reserialize_one_of_default_type() {
1097 let a = OneOf::new()
1098 .item(Schema::Array(Array::new().items(RefOr::Type(
1099 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
1100 ))))
1101 .item(Schema::Array(Array::new().items(RefOr::Type(
1102 Schema::object(Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar")))),
1103 ))));
1104
1105 let serialized_json = serde_json::to_string(&a).expect("should serialize to json");
1106 let b: OneOf = serde_json::from_str(&serialized_json).expect("should deserialize OneOf");
1107 let reserialized_json = serde_json::to_string(&b).expect("reserialized json");
1108
1109 assert_eq!(serialized_json, reserialized_json);
1110 }
1111
1112 #[test]
1113 fn serialize_deserialize_object_with_multiple_schema_types() {
1114 let object =
1115 Object::new().schema_type(SchemaType::from_iter([BasicType::Object, BasicType::Null]));
1116
1117 let json_str = serde_json::to_string(&object).expect("serde json should success");
1118 let deserialized: Object =
1119 serde_json::from_str(&json_str).expect("serde json should success");
1120 let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
1121 assert_eq!(json_str, json_de_str);
1122 }
1123
1124 #[test]
1125 fn test_empty_schema() {
1126 let schema = empty();
1127 assert_json_eq!(
1128 schema,
1129 json!({
1130 "default": null
1131 })
1132 )
1133 }
1134
1135 #[test]
1136 fn test_default_schema() {
1137 let schema = Schema::default();
1138 assert_json_eq!(
1139 schema,
1140 json!({
1141 "type": "object",
1142 })
1143 )
1144 }
1145
1146 #[test]
1147 fn test_ref_from_response_name() {
1148 let _ref = Ref::from_response_name("MyResponse");
1149 assert_json_eq!(
1150 _ref,
1151 json!({
1152 "$ref": "#/components/responses/MyResponse"
1153 })
1154 )
1155 }
1156
1157 #[test]
1158 fn test_additional_properties_from_ref_or() {
1159 let additional_properties =
1160 AdditionalProperties::from(RefOr::Type(Schema::Object(Box::default())));
1161 assert_json_eq!(
1162 additional_properties,
1163 json!({
1164 "type": "object",
1165 })
1166 )
1167 }
1168}