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 = "PropMap::is_empty", flatten)]
199 pub extensions: PropMap<String, serde_json::Value>,
200}
201
202impl Discriminator {
203 pub fn new<I: Into<String>>(property_name: I) -> Self {
213 Self {
214 property_name: property_name.into(),
215 mapping: PropMap::new(),
216 extensions: PropMap::new(),
217 }
218 }
219
220 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
222 self.extensions = extensions;
223 self
224 }
225}
226
227#[allow(clippy::trivially_copy_pass_by_ref)]
228fn is_false(value: &bool) -> bool {
229 !*value
230}
231
232#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
236#[serde(untagged)]
237pub enum AdditionalProperties<T> {
238 RefOr(RefOr<T>),
240 FreeForm(bool),
242}
243
244impl<T> From<RefOr<T>> for AdditionalProperties<T> {
245 fn from(value: RefOr<T>) -> Self {
246 Self::RefOr(value)
247 }
248}
249
250impl From<Object> for AdditionalProperties<Schema> {
251 fn from(value: Object) -> Self {
252 Self::RefOr(RefOr::Type(Schema::object(value)))
253 }
254}
255
256impl From<Array> for AdditionalProperties<Schema> {
257 fn from(value: Array) -> Self {
258 Self::RefOr(RefOr::Type(Schema::Array(value)))
259 }
260}
261
262impl From<Ref> for AdditionalProperties<Schema> {
263 fn from(value: Ref) -> Self {
264 Self::RefOr(RefOr::Ref(value))
265 }
266}
267
268impl From<OneOf> for AdditionalProperties<Schema> {
269 fn from(value: OneOf) -> Self {
270 Self::RefOr(RefOr::Type(Schema::OneOf(value)))
271 }
272}
273
274#[non_exhaustive]
279#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
280pub struct Ref {
281 #[serde(rename = "$ref")]
283 pub ref_location: String,
284
285 #[serde(skip_serializing_if = "String::is_empty", default)]
289 pub description: String,
290
291 #[serde(skip_serializing_if = "String::is_empty", default)]
294 pub summary: String,
295}
296
297impl Ref {
298 #[must_use]
301 pub fn new<I: Into<String>>(ref_location: I) -> Self {
302 Self {
303 ref_location: ref_location.into(),
304 ..Default::default()
305 }
306 }
307
308 #[must_use]
311 pub fn from_schema_name<I: Into<String>>(schema_name: I) -> Self {
312 Self::new(format!("#/components/schemas/{}", schema_name.into()))
313 }
314
315 #[must_use]
318 pub fn from_response_name<I: Into<String>>(response_name: I) -> Self {
319 Self::new(format!("#/components/responses/{}", response_name.into()))
320 }
321
322 #[must_use]
324 pub fn ref_location(mut self, ref_location: String) -> Self {
325 self.ref_location = ref_location;
326 self
327 }
328
329 #[must_use]
332 pub fn ref_location_from_schema_name<S: Into<String>>(mut self, schema_name: S) -> Self {
333 self.ref_location = format!("#/components/schemas/{}", schema_name.into());
334 self
335 }
336
337 #[must_use]
343 pub fn description<S: Into<String>>(mut self, description: S) -> Self {
344 self.description = description.into();
345 self
346 }
347
348 #[must_use]
352 pub fn summary<S: Into<String>>(mut self, summary: S) -> Self {
353 self.summary = summary.into();
354 self
355 }
356
357 #[must_use]
359 pub fn to_array(self) -> Array {
360 Array::new().items(self)
361 }
362}
363
364impl From<Ref> for RefOr<Schema> {
365 fn from(r: Ref) -> Self {
366 Self::Ref(r)
367 }
368}
369
370impl<T> From<T> for RefOr<T> {
371 fn from(t: T) -> Self {
372 Self::Type(t)
373 }
374}
375
376impl Default for RefOr<Schema> {
377 fn default() -> Self {
378 Self::Type(Schema::object(Object::new()))
379 }
380}
381
382#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
386#[serde(untagged)]
387pub enum SchemaType {
388 Basic(BasicType),
390 Array(Vec<BasicType>),
392 AnyValue,
395}
396
397impl Default for SchemaType {
398 fn default() -> Self {
399 Self::Basic(BasicType::default())
400 }
401}
402
403impl From<BasicType> for SchemaType {
404 fn from(value: BasicType) -> Self {
405 Self::basic(value)
406 }
407}
408
409impl FromIterator<BasicType> for SchemaType {
410 fn from_iter<T: IntoIterator<Item = BasicType>>(iter: T) -> Self {
411 Self::Array(iter.into_iter().collect())
412 }
413}
414impl SchemaType {
415 #[must_use]
427 pub fn basic(r#type: BasicType) -> Self {
428 Self::Basic(r#type)
429 }
430
431 #[must_use]
435 pub fn any() -> Self {
436 Self::AnyValue
437 }
438
439 #[must_use]
442 pub fn is_any_value(&self) -> bool {
443 matches!(self, Self::AnyValue)
444 }
445}
446
447#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
467#[serde(rename_all = "lowercase")]
468pub enum BasicType {
469 #[default]
471 Object,
472 String,
475 Integer,
478 Number,
481 Boolean,
484 Array,
486 Null,
488}
489
490#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
496#[serde(rename_all = "lowercase", untagged)]
497pub enum SchemaFormat {
498 KnownFormat(KnownFormat),
500 Custom(String),
503}
504
505#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
511#[serde(rename_all = "kebab-case")]
512pub enum KnownFormat {
513 Int8,
515 Int16,
517 Int32,
519 Int64,
521 #[serde(rename = "uint8")]
523 UInt8,
524 #[serde(rename = "uint16")]
526 UInt16,
527 #[serde(rename = "uint32")]
529 UInt32,
530 #[serde(rename = "uint64")]
532 UInt64,
533 Float,
535 Double,
537 Byte,
539 Binary,
541 Time,
543 Date,
545 DateTime,
547 Duration,
549 Password,
551 String,
553 #[cfg(any(feature = "decimal", feature = "decimal-float"))]
557 #[cfg_attr(docsrs, doc(cfg(any(feature = "decimal", feature = "decimal-float"))))]
558 Decimal,
559 #[cfg(feature = "ulid")]
561 #[cfg_attr(docsrs, doc(cfg(feature = "ulid")))]
562 Ulid,
563
564 #[cfg(feature = "uuid")]
566 #[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
567 Uuid,
568 #[cfg(feature = "url")]
572 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
573 Url,
574 #[cfg(feature = "url")]
578 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
579 UriReference,
580 #[cfg(feature = "url")]
583 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
584 Iri,
585 #[cfg(feature = "url")]
589 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
590 IriReference,
591 Email,
593 IdnEmail,
595 Hostname,
599 IdnHostname,
602 Ipv4,
604 Ipv6,
606 UriTemplate,
611 JsonPointer,
613 RelativeJsonPointer,
615 Regex,
618}
619
620#[cfg(test)]
621mod tests {
622 use assert_json_diff::assert_json_eq;
623 use serde_json::{Value, json};
624
625 use super::*;
626 use crate::*;
627
628 #[test]
629 fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
630 let openapi = OpenApi::new("My api", "1.0.0").components(
631 Components::new()
632 .add_schema("Person", Ref::new("#/components/PersonModel"))
633 .add_schema(
634 "Credential",
635 Schema::from(
636 Object::new()
637 .property(
638 "id",
639 Object::new()
640 .schema_type(BasicType::Integer)
641 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
642 .description("Id of credential")
643 .default_value(json!(1i32)),
644 )
645 .property(
646 "name",
647 Object::new()
648 .schema_type(BasicType::String)
649 .description("Name of credential"),
650 )
651 .property(
652 "status",
653 Object::new()
654 .schema_type(BasicType::String)
655 .default_value(json!("Active"))
656 .description("Credential status")
657 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
658 )
659 .property(
660 "history",
661 Array::new().items(Ref::from_schema_name("UpdateHistory")),
662 )
663 .property("tags", Object::with_type(BasicType::String).to_array()),
664 ),
665 ),
666 );
667
668 let serialized = serde_json::to_string_pretty(&openapi)?;
669 println!("serialized json:\n {serialized}");
670
671 let value = serde_json::to_value(&openapi)?;
672 let credential = get_json_path(&value, "components.schemas.Credential.properties");
673 let person = get_json_path(&value, "components.schemas.Person");
674
675 assert!(
676 credential.get("id").is_some(),
677 "could not find path: components.schemas.Credential.properties.id"
678 );
679 assert!(
680 credential.get("status").is_some(),
681 "could not find path: components.schemas.Credential.properties.status"
682 );
683 assert!(
684 credential.get("name").is_some(),
685 "could not find path: components.schemas.Credential.properties.name"
686 );
687 assert!(
688 credential.get("history").is_some(),
689 "could not find path: components.schemas.Credential.properties.history"
690 );
691 assert_json_eq!(
692 credential
693 .get("id")
694 .unwrap_or(&serde_json::value::Value::Null),
695 json!({"type":"integer","format":"int32","description":"Id of credential","default":1})
696 );
697 assert_json_eq!(
698 credential
699 .get("name")
700 .unwrap_or(&serde_json::value::Value::Null),
701 json!({"type":"string","description":"Name of credential"})
702 );
703 assert_json_eq!(
704 credential
705 .get("status")
706 .unwrap_or(&serde_json::value::Value::Null),
707 json!({"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"})
708 );
709 assert_json_eq!(
710 credential
711 .get("history")
712 .unwrap_or(&serde_json::value::Value::Null),
713 json!({"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"})
714 );
715 assert_eq!(person, &json!({"$ref":"#/components/PersonModel"}));
716
717 Ok(())
718 }
719
720 #[test]
722 fn test_property_order() {
723 let json_value = Object::new()
724 .property(
725 "id",
726 Object::new()
727 .schema_type(BasicType::Integer)
728 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
729 .description("Id of credential")
730 .default_value(json!(1i32)),
731 )
732 .property(
733 "name",
734 Object::new()
735 .schema_type(BasicType::String)
736 .description("Name of credential"),
737 )
738 .property(
739 "status",
740 Object::new()
741 .schema_type(BasicType::String)
742 .default_value(json!("Active"))
743 .description("Credential status")
744 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
745 )
746 .property(
747 "history",
748 Array::new().items(Ref::from_schema_name("UpdateHistory")),
749 )
750 .property("tags", Object::with_type(BasicType::String).to_array());
751
752 #[cfg(not(feature = "preserve-order"))]
753 assert_eq!(
754 json_value.properties.keys().collect::<Vec<_>>(),
755 vec!["history", "id", "name", "status", "tags"]
756 );
757
758 #[cfg(feature = "preserve-order")]
759 assert_eq!(
760 json_value.properties.keys().collect::<Vec<_>>(),
761 vec!["id", "name", "status", "history", "tags"]
762 );
763 }
764
765 #[test]
767 fn test_additional_properties() {
768 let json_value =
769 Object::new().additional_properties(Object::new().schema_type(BasicType::String));
770 assert_json_eq!(
771 json_value,
772 json!({
773 "type": "object",
774 "additionalProperties": {
775 "type": "string"
776 }
777 })
778 );
779
780 let json_value = Object::new().additional_properties(
781 Array::new().items(Object::new().schema_type(BasicType::Number)),
782 );
783 assert_json_eq!(
784 json_value,
785 json!({
786 "type": "object",
787 "additionalProperties": {
788 "items": {
789 "type": "number",
790 },
791 "type": "array",
792 }
793 })
794 );
795
796 let json_value = Object::new().additional_properties(Ref::from_schema_name("ComplexModel"));
797 assert_json_eq!(
798 json_value,
799 json!({
800 "type": "object",
801 "additionalProperties": {
802 "$ref": "#/components/schemas/ComplexModel"
803 }
804 })
805 )
806 }
807
808 #[test]
809 fn test_object_with_name() {
810 let json_value = Object::new().name("SomeName");
811 assert_json_eq!(
812 json_value,
813 json!({
814 "type": "object",
815 "name": "SomeName"
816 })
817 );
818 }
819
820 #[test]
821 fn test_derive_object_with_examples() {
822 let expected = r#"{"type":"object","examples":[{"age":20,"name":"bob the cat"}]}"#;
823 let json_value = Object::new().examples([json!({"age": 20, "name": "bob the cat"})]);
824
825 let value_string = serde_json::to_string(&json_value).unwrap();
826 assert_eq!(
827 value_string, expected,
828 "value string != expected string, {value_string} != {expected}"
829 );
830 }
831
832 fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
833 path.split('.').fold(value, |acc, fragment| {
834 acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
835 })
836 }
837
838 #[test]
839 fn test_array_new() {
840 let 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 test_array_builder() {
859 let array: Array = Array::new().items(
860 Object::new().property(
861 "id",
862 Object::new()
863 .schema_type(BasicType::Integer)
864 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
865 .description("Id of credential")
866 .default_value(json!(1i32)),
867 ),
868 );
869
870 assert!(matches!(
871 array.schema_type,
872 SchemaType::Basic(BasicType::Array)
873 ));
874 }
875
876 #[test]
877 fn reserialize_deserialized_schema_components() {
878 let components = Components::new()
879 .extend_schemas(vec![(
880 "Comp",
881 Schema::from(
882 Object::new()
883 .property("name", Object::new().schema_type(BasicType::String))
884 .required("name"),
885 ),
886 )])
887 .response("204", Response::new("No Content"))
888 .extend_responses(vec![("200", Response::new("Okay"))])
889 .add_security_scheme("TLS", SecurityScheme::MutualTls { description: None })
890 .extend_security_schemes(vec![(
891 "APIKey",
892 SecurityScheme::Http(security::Http::default()),
893 )]);
894
895 let serialized_components = serde_json::to_string(&components).unwrap();
896
897 let deserialized_components: Components =
898 serde_json::from_str(serialized_components.as_str()).unwrap();
899
900 assert_eq!(
901 serialized_components,
902 serde_json::to_string(&deserialized_components).unwrap()
903 )
904 }
905
906 #[test]
907 fn reserialize_deserialized_object_component() {
908 let prop = Object::new()
909 .property("name", Object::new().schema_type(BasicType::String))
910 .required("name");
911
912 let serialized_components = serde_json::to_string(&prop).unwrap();
913 let deserialized_components: Object =
914 serde_json::from_str(serialized_components.as_str()).unwrap();
915
916 assert_eq!(
917 serialized_components,
918 serde_json::to_string(&deserialized_components).unwrap()
919 )
920 }
921
922 #[test]
923 fn reserialize_deserialized_property() {
924 let prop = Object::new().schema_type(BasicType::String);
925
926 let serialized_components = serde_json::to_string(&prop).unwrap();
927 let deserialized_components: Object =
928 serde_json::from_str(serialized_components.as_str()).unwrap();
929
930 assert_eq!(
931 serialized_components,
932 serde_json::to_string(&deserialized_components).unwrap()
933 )
934 }
935
936 #[test]
937 fn serialize_deserialize_array_within_ref_or_t_object_builder() {
938 let ref_or_schema = RefOr::Type(Schema::object(Object::new().property(
939 "test",
940 RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
941 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
942 )))),
943 )));
944
945 let json_str = serde_json::to_string(&ref_or_schema).expect("");
946 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
947 let json_de_str = serde_json::to_string(&deserialized).expect("");
948 assert_eq!(json_str, json_de_str);
949 }
950
951 #[test]
952 fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
953 let ref_or_schema = RefOr::Type(Schema::object(
954 Object::new().property(
955 "test",
956 RefOr::Type(Schema::OneOf(
957 OneOf::new()
958 .item(Schema::Array(Array::new().items(RefOr::Type(
959 Schema::object(
960 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
961 ),
962 ))))
963 .item(Schema::Array(Array::new().items(RefOr::Type(
964 Schema::object(
965 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
966 ),
967 )))),
968 )),
969 ),
970 ));
971
972 let json_str = serde_json::to_string(&ref_or_schema).expect("");
973 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
974 let json_de_str = serde_json::to_string(&deserialized).expect("");
975 assert_eq!(json_str, json_de_str);
976 }
977
978 #[test]
979 fn serialize_deserialize_all_of_of_within_ref_or_t_object() {
980 let ref_or_schema = RefOr::Type(Schema::object(
981 Object::new().property(
982 "test",
983 RefOr::Type(Schema::AllOf(
984 AllOf::new()
985 .item(Schema::Array(Array::new().items(RefOr::Type(
986 Schema::object(
987 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
988 ),
989 ))))
990 .item(RefOr::Type(Schema::object(
991 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
992 ))),
993 )),
994 ),
995 ));
996
997 let json_str = serde_json::to_string(&ref_or_schema).expect("");
998 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
999 let json_de_str = serde_json::to_string(&deserialized).expect("");
1000 assert_eq!(json_str, json_de_str);
1001 }
1002
1003 #[test]
1004 fn serialize_deserialize_any_of_of_within_ref_or_t_object() {
1005 let ref_or_schema = RefOr::Type(Schema::object(
1006 Object::new().property(
1007 "test",
1008 RefOr::Type(Schema::AnyOf(
1009 AnyOf::new()
1010 .item(Schema::Array(Array::new().items(RefOr::Type(
1011 Schema::object(
1012 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1013 ),
1014 ))))
1015 .item(RefOr::Type(Schema::object(
1016 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
1017 ))),
1018 )),
1019 ),
1020 ));
1021
1022 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1023 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1024 let json_de_str = serde_json::to_string(&deserialized).expect("");
1025 assert!(json_str.contains("\"anyOf\""));
1026 assert_eq!(json_str, json_de_str);
1027 }
1028
1029 #[test]
1030 fn serialize_deserialize_schema_array_ref_or_t() {
1031 let ref_or_schema = RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
1032 Schema::Object(Box::new(
1033 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1034 )),
1035 ))));
1036
1037 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1038 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1039 let json_de_str = serde_json::to_string(&deserialized).expect("");
1040 assert_eq!(json_str, json_de_str);
1041 }
1042
1043 #[test]
1044 fn serialize_deserialize_schema_array() {
1045 let ref_or_schema = Array::new().items(RefOr::Type(Schema::object(
1046 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1047 )));
1048
1049 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1050 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1051 let json_de_str = serde_json::to_string(&deserialized).expect("");
1052 assert_eq!(json_str, json_de_str);
1053 }
1054
1055 #[test]
1056 fn serialize_deserialize_schema_with_additional_properties() {
1057 let schema = Schema::object(Object::new().property(
1058 "map",
1059 Object::new().additional_properties(AdditionalProperties::FreeForm(true)),
1060 ));
1061
1062 let json_str = serde_json::to_string(&schema).unwrap();
1063 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
1064 let json_de_str = serde_json::to_string(&deserialized).unwrap();
1065 assert_eq!(json_str, json_de_str);
1066 }
1067
1068 #[test]
1069 fn serialize_deserialize_schema_with_additional_properties_object() {
1070 let schema = Schema::object(Object::new().property(
1071 "map",
1072 Object::new().additional_properties(
1073 Object::new().property("name", Object::with_type(BasicType::String)),
1074 ),
1075 ));
1076
1077 let json_str = serde_json::to_string(&schema).expect("serde json should success");
1078 let deserialized: RefOr<Schema> =
1079 serde_json::from_str(&json_str).expect("serde json should success");
1080 let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
1081 assert_eq!(json_str, json_de_str);
1082 }
1083
1084 #[test]
1085 fn serialize_discriminator_with_mapping() {
1086 let mut discriminator = Discriminator::new("type");
1087 discriminator.mapping = [("int".to_owned(), "#/components/schemas/MyInt".to_owned())]
1088 .into_iter()
1089 .collect::<PropMap<_, _>>();
1090 let one_of = OneOf::new()
1091 .item(Ref::from_schema_name("MyInt"))
1092 .discriminator(discriminator);
1093 let json_value = serde_json::to_value(one_of).expect("serde json should success");
1094
1095 assert_json_eq!(
1096 json_value,
1097 json!({
1098 "oneOf": [
1099 {
1100 "$ref": "#/components/schemas/MyInt"
1101 }
1102 ],
1103 "discriminator": {
1104 "propertyName": "type",
1105 "mapping": {
1106 "int": "#/components/schemas/MyInt"
1107 }
1108 }
1109 })
1110 );
1111 }
1112
1113 #[test]
1114 fn deserialize_reserialize_one_of_default_type() {
1115 let a = OneOf::new()
1116 .item(Schema::Array(Array::new().items(RefOr::Type(
1117 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
1118 ))))
1119 .item(Schema::Array(Array::new().items(RefOr::Type(
1120 Schema::object(Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar")))),
1121 ))));
1122
1123 let serialized_json = serde_json::to_string(&a).expect("should serialize to json");
1124 let b: OneOf = serde_json::from_str(&serialized_json).expect("should deserialize OneOf");
1125 let reserialized_json = serde_json::to_string(&b).expect("reserialized json");
1126
1127 assert_eq!(serialized_json, reserialized_json);
1128 }
1129
1130 #[test]
1131 fn serialize_deserialize_object_with_multiple_schema_types() {
1132 let object =
1133 Object::new().schema_type(SchemaType::from_iter([BasicType::Object, BasicType::Null]));
1134
1135 let json_str = serde_json::to_string(&object).expect("serde json should success");
1136 let deserialized: Object =
1137 serde_json::from_str(&json_str).expect("serde json should success");
1138 let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
1139 assert_eq!(json_str, json_de_str);
1140 }
1141
1142 #[test]
1143 fn test_empty_schema() {
1144 let schema = empty();
1145 assert_json_eq!(
1146 schema,
1147 json!({
1148 "default": null
1149 })
1150 )
1151 }
1152
1153 #[test]
1154 fn test_default_schema() {
1155 let schema = Schema::default();
1156 assert_json_eq!(
1157 schema,
1158 json!({
1159 "type": "object",
1160 })
1161 )
1162 }
1163
1164 #[test]
1165 fn test_ref_from_response_name() {
1166 let _ref = Ref::from_response_name("MyResponse");
1167 assert_json_eq!(
1168 _ref,
1169 json!({
1170 "$ref": "#/components/responses/MyResponse"
1171 })
1172 )
1173 }
1174
1175 #[test]
1176 fn test_additional_properties_from_ref_or() {
1177 let additional_properties =
1178 AdditionalProperties::from(RefOr::Type(Schema::Object(Box::default())));
1179 assert_json_eq!(
1180 additional_properties,
1181 json!({
1182 "type": "object",
1183 })
1184 )
1185 }
1186}