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 pub fn new() -> Self {
83 Default::default()
84 }
85 pub fn schema<K: Into<String>, V: Into<RefOr<Schema>>>(mut self, key: K, value: V) -> Self {
87 self.insert(key, value);
88 self
89 }
90 pub fn insert<K: Into<String>, V: Into<RefOr<Schema>>>(&mut self, key: K, value: V) {
92 self.0.insert(key.into(), value.into());
93 }
94 pub fn append(&mut self, other: &mut Schemas) {
99 let items = std::mem::take(&mut other.0);
100 for item in items {
101 self.insert(item.0, item.1);
102 }
103 }
104 pub fn extend<I, K, V>(&mut self, iter: I)
106 where
107 I: IntoIterator<Item = (K, V)>,
108 K: Into<String>,
109 V: Into<RefOr<Schema>>,
110 {
111 for (k, v) in iter.into_iter() {
112 self.insert(k, v);
113 }
114 }
115}
116
117pub fn empty() -> Schema {
122 Schema::object(
123 Object::new()
124 .schema_type(SchemaType::AnyValue)
125 .default_value(serde_json::Value::Null),
126 )
127}
128
129#[non_exhaustive]
134#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
135#[serde(untagged, rename_all = "camelCase")]
136pub enum Schema {
137 Array(Array),
140 Object(Box<Object>),
143 OneOf(OneOf),
149
150 AllOf(AllOf),
154
155 AnyOf(AnyOf),
159}
160
161impl Default for Schema {
162 fn default() -> Self {
163 Schema::Object(Default::default())
164 }
165}
166
167impl Schema {
168 pub fn object(obj: Object) -> Self {
170 Self::Object(Box::new(obj))
171 }
172}
173
174#[non_exhaustive]
179#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
180#[serde(rename_all = "camelCase")]
181pub struct Discriminator {
182 pub property_name: String,
185
186 #[serde(skip_serializing_if = "PropMap::is_empty", default)]
190 pub mapping: PropMap<String, String>,
191}
192
193impl Discriminator {
194 pub fn new<I: Into<String>>(property_name: I) -> Self {
204 Self {
205 property_name: property_name.into(),
206 mapping: PropMap::new(),
207 }
208 }
209}
210
211fn is_false(value: &bool) -> bool {
212 !*value
213}
214
215#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
219#[serde(untagged)]
220pub enum AdditionalProperties<T> {
221 RefOr(RefOr<T>),
223 FreeForm(bool),
225}
226
227impl<T> From<RefOr<T>> for AdditionalProperties<T> {
228 fn from(value: RefOr<T>) -> Self {
229 Self::RefOr(value)
230 }
231}
232
233impl From<Object> for AdditionalProperties<Schema> {
234 fn from(value: Object) -> Self {
235 Self::RefOr(RefOr::Type(Schema::object(value)))
236 }
237}
238
239impl From<Array> for AdditionalProperties<Schema> {
240 fn from(value: Array) -> Self {
241 Self::RefOr(RefOr::Type(Schema::Array(value)))
242 }
243}
244
245impl From<Ref> for AdditionalProperties<Schema> {
246 fn from(value: Ref) -> Self {
247 Self::RefOr(RefOr::Ref(value))
248 }
249}
250
251#[non_exhaustive]
256#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
257pub struct Ref {
258 #[serde(rename = "$ref")]
260 pub ref_location: String,
261
262 #[serde(skip_serializing_if = "String::is_empty", default)]
266 pub description: String,
267
268 #[serde(skip_serializing_if = "String::is_empty", default)]
271 pub summary: String,
272}
273
274impl Ref {
275 pub fn new<I: Into<String>>(ref_location: I) -> Self {
278 Self {
279 ref_location: ref_location.into(),
280 ..Default::default()
281 }
282 }
283
284 pub fn from_schema_name<I: Into<String>>(schema_name: I) -> Self {
287 Self::new(format!("#/components/schemas/{}", schema_name.into()))
288 }
289
290 pub fn from_response_name<I: Into<String>>(response_name: I) -> Self {
293 Self::new(format!("#/components/responses/{}", response_name.into()))
294 }
295
296 pub fn ref_location(mut self, ref_location: String) -> Self {
298 self.ref_location = ref_location;
299 self
300 }
301
302 pub fn ref_location_from_schema_name<S: Into<String>>(mut self, schema_name: S) -> Self {
305 self.ref_location = format!("#/components/schemas/{}", schema_name.into());
306 self
307 }
308
309 pub fn description<S: Into<String>>(mut self, description: S) -> Self {
315 self.description = description.into();
316 self
317 }
318
319 pub fn summary<S: Into<String>>(mut self, summary: S) -> Self {
322 self.summary = summary.into();
323 self
324 }
325}
326
327impl From<Ref> for RefOr<Schema> {
328 fn from(r: Ref) -> Self {
329 Self::Ref(r)
330 }
331}
332
333impl<T> From<T> for RefOr<T> {
334 fn from(t: T) -> Self {
335 Self::Type(t)
336 }
337}
338
339impl Default for RefOr<Schema> {
340 fn default() -> Self {
341 Self::Type(Schema::object(Object::new()))
342 }
343}
344
345impl ToArray for RefOr<Schema> {}
346
347#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
349#[serde(untagged)]
350pub enum SchemaType {
351 Basic(BasicType),
353 Array(Vec<BasicType>),
355 AnyValue,
358}
359
360impl Default for SchemaType {
361 fn default() -> Self {
362 Self::Basic(BasicType::default())
363 }
364}
365
366impl From<BasicType> for SchemaType {
367 fn from(value: BasicType) -> Self {
368 SchemaType::basic(value)
369 }
370}
371
372impl FromIterator<BasicType> for SchemaType {
373 fn from_iter<T: IntoIterator<Item = BasicType>>(iter: T) -> Self {
374 Self::Array(iter.into_iter().collect())
375 }
376}
377impl SchemaType {
378 pub fn basic(r#type: BasicType) -> Self {
390 Self::Basic(r#type)
391 }
392
393 pub fn any() -> Self {
398 SchemaType::AnyValue
399 }
400
401 pub fn is_any_value(&self) -> bool {
404 matches!(self, Self::AnyValue)
405 }
406}
407
408#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
428#[serde(rename_all = "lowercase")]
429pub enum BasicType {
430 #[default]
432 Object,
433 String,
436 Integer,
439 Number,
442 Boolean,
445 Array,
447 Null,
449}
450
451#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
457#[serde(rename_all = "lowercase", untagged)]
458pub enum SchemaFormat {
459 KnownFormat(KnownFormat),
461 Custom(String),
464}
465
466#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
472#[serde(rename_all = "kebab-case")]
473pub enum KnownFormat {
474 Int8,
476 Int16,
478 Int32,
480 Int64,
482 #[serde(rename = "uint8")]
484 UInt8,
485 #[serde(rename = "uint16")]
487 UInt16,
488 #[serde(rename = "uint32")]
490 UInt32,
491 #[serde(rename = "uint64")]
493 UInt64,
494 Float,
496 Double,
498 Byte,
500 Binary,
502 Time,
504 Date,
506 DateTime,
508 Duration,
510 Password,
512 String,
514 #[cfg(any(feature = "decimal", feature = "decimal-float"))]
518 #[cfg_attr(docsrs, doc(cfg(any(feature = "decimal", feature = "decimal-float"))))]
519 Decimal,
520 #[cfg(feature = "ulid")]
522 #[cfg_attr(docsrs, doc(cfg(feature = "ulid")))]
523 Ulid,
524
525 #[cfg(feature = "uuid")]
527 #[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
528 Uuid,
529 #[cfg(feature = "url")]
533 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
534 Url,
535 #[cfg(feature = "url")]
539 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
540 UriReference,
541 #[cfg(feature = "url")]
544 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
545 Iri,
546 #[cfg(feature = "url")]
550 #[cfg_attr(docsrs, doc(cfg(feature = "url")))]
551 IriReference,
552 Email,
554 IdnEmail,
556 Hostname,
560 IdnHostname,
563 Ipv4,
565 Ipv6,
567 UriTemplate,
572 JsonPointer,
574 RelativeJsonPointer,
576 Regex,
579}
580
581#[cfg(test)]
582mod tests {
583 use assert_json_diff::assert_json_eq;
584 use serde_json::{Value, json};
585
586 use super::*;
587 use crate::*;
588
589 #[test]
590 fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
591 let openapi = OpenApi::new("My api", "1.0.0").components(
592 Components::new()
593 .add_schema("Person", Ref::new("#/components/PersonModel"))
594 .add_schema(
595 "Credential",
596 Schema::from(
597 Object::new()
598 .property(
599 "id",
600 Object::new()
601 .schema_type(BasicType::Integer)
602 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
603 .description("Id of credential")
604 .default_value(json!(1i32)),
605 )
606 .property(
607 "name",
608 Object::new()
609 .schema_type(BasicType::String)
610 .description("Name of credential"),
611 )
612 .property(
613 "status",
614 Object::new()
615 .schema_type(BasicType::String)
616 .default_value(json!("Active"))
617 .description("Credential status")
618 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
619 )
620 .property(
621 "history",
622 Array::new().items(Ref::from_schema_name("UpdateHistory")),
623 )
624 .property("tags", Object::with_type(BasicType::String).to_array()),
625 ),
626 ),
627 );
628
629 let serialized = serde_json::to_string_pretty(&openapi)?;
630 println!("serialized json:\n {serialized}");
631
632 let value = serde_json::to_value(&openapi)?;
633 let credential = get_json_path(&value, "components.schemas.Credential.properties");
634 let person = get_json_path(&value, "components.schemas.Person");
635
636 assert!(
637 credential.get("id").is_some(),
638 "could not find path: components.schemas.Credential.properties.id"
639 );
640 assert!(
641 credential.get("status").is_some(),
642 "could not find path: components.schemas.Credential.properties.status"
643 );
644 assert!(
645 credential.get("name").is_some(),
646 "could not find path: components.schemas.Credential.properties.name"
647 );
648 assert!(
649 credential.get("history").is_some(),
650 "could not find path: components.schemas.Credential.properties.history"
651 );
652 assert_json_eq!(
653 credential
654 .get("id")
655 .unwrap_or(&serde_json::value::Value::Null),
656 json!({"type":"integer","format":"int32","description":"Id of credential","default":1})
657 );
658 assert_json_eq!(
659 credential
660 .get("name")
661 .unwrap_or(&serde_json::value::Value::Null),
662 json!({"type":"string","description":"Name of credential"})
663 );
664 assert_json_eq!(
665 credential
666 .get("status")
667 .unwrap_or(&serde_json::value::Value::Null),
668 json!({"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"})
669 );
670 assert_json_eq!(
671 credential
672 .get("history")
673 .unwrap_or(&serde_json::value::Value::Null),
674 json!({"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"})
675 );
676 assert_eq!(person, &json!({"$ref":"#/components/PersonModel"}));
677
678 Ok(())
679 }
680
681 #[test]
683 fn test_property_order() {
684 let json_value = Object::new()
685 .property(
686 "id",
687 Object::new()
688 .schema_type(BasicType::Integer)
689 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
690 .description("Id of credential")
691 .default_value(json!(1i32)),
692 )
693 .property(
694 "name",
695 Object::new()
696 .schema_type(BasicType::String)
697 .description("Name of credential"),
698 )
699 .property(
700 "status",
701 Object::new()
702 .schema_type(BasicType::String)
703 .default_value(json!("Active"))
704 .description("Credential status")
705 .enum_values(["Active", "NotActive", "Locked", "Expired"]),
706 )
707 .property(
708 "history",
709 Array::new().items(Ref::from_schema_name("UpdateHistory")),
710 )
711 .property("tags", Object::with_type(BasicType::String).to_array());
712
713 #[cfg(not(feature = "preserve-order"))]
714 assert_eq!(
715 json_value.properties.keys().collect::<Vec<_>>(),
716 vec!["history", "id", "name", "status", "tags"]
717 );
718
719 #[cfg(feature = "preserve-order")]
720 assert_eq!(
721 json_value.properties.keys().collect::<Vec<_>>(),
722 vec!["id", "name", "status", "history", "tags"]
723 );
724 }
725
726 #[test]
728 fn test_additional_properties() {
729 let json_value =
730 Object::new().additional_properties(Object::new().schema_type(BasicType::String));
731 assert_json_eq!(
732 json_value,
733 json!({
734 "type": "object",
735 "additionalProperties": {
736 "type": "string"
737 }
738 })
739 );
740
741 let json_value = Object::new().additional_properties(
742 Array::new().items(Object::new().schema_type(BasicType::Number)),
743 );
744 assert_json_eq!(
745 json_value,
746 json!({
747 "type": "object",
748 "additionalProperties": {
749 "items": {
750 "type": "number",
751 },
752 "type": "array",
753 }
754 })
755 );
756
757 let json_value = Object::new().additional_properties(Ref::from_schema_name("ComplexModel"));
758 assert_json_eq!(
759 json_value,
760 json!({
761 "type": "object",
762 "additionalProperties": {
763 "$ref": "#/components/schemas/ComplexModel"
764 }
765 })
766 )
767 }
768
769 #[test]
770 fn test_object_with_name() {
771 let json_value = Object::new().name("SomeName");
772 assert_json_eq!(
773 json_value,
774 json!({
775 "type": "object",
776 "name": "SomeName"
777 })
778 );
779 }
780
781 #[test]
782 fn test_derive_object_with_examples() {
783 let expected = r#"{"type":"object","examples":[{"age":20,"name":"bob the cat"}]}"#;
784 let json_value = Object::new().examples([json!({"age": 20, "name": "bob the cat"})]);
785
786 let value_string = serde_json::to_string(&json_value).unwrap();
787 assert_eq!(
788 value_string, expected,
789 "value string != expected string, {value_string} != {expected}"
790 );
791 }
792
793 fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
794 path.split('.').fold(value, |acc, fragment| {
795 acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
796 })
797 }
798
799 #[test]
800 fn test_array_new() {
801 let array = Array::new().items(
802 Object::new().property(
803 "id",
804 Object::new()
805 .schema_type(BasicType::Integer)
806 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
807 .description("Id of credential")
808 .default_value(json!(1i32)),
809 ),
810 );
811
812 assert!(matches!(
813 array.schema_type,
814 SchemaType::Basic(BasicType::Array)
815 ));
816 }
817
818 #[test]
819 fn test_array_builder() {
820 let array: Array = Array::new().items(
821 Object::new().property(
822 "id",
823 Object::new()
824 .schema_type(BasicType::Integer)
825 .format(SchemaFormat::KnownFormat(KnownFormat::Int32))
826 .description("Id of credential")
827 .default_value(json!(1i32)),
828 ),
829 );
830
831 assert!(matches!(
832 array.schema_type,
833 SchemaType::Basic(BasicType::Array)
834 ));
835 }
836
837 #[test]
838 fn reserialize_deserialized_schema_components() {
839 let components = Components::new()
840 .extend_schemas(vec![(
841 "Comp",
842 Schema::from(
843 Object::new()
844 .property("name", Object::new().schema_type(BasicType::String))
845 .required("name"),
846 ),
847 )])
848 .response("204", Response::new("No Content"))
849 .extend_responses(vec![("200", Response::new("Okay"))])
850 .add_security_scheme("TLS", SecurityScheme::MutualTls { description: None })
851 .extend_security_schemes(vec![(
852 "APIKey",
853 SecurityScheme::Http(security::Http::default()),
854 )]);
855
856 let serialized_components = serde_json::to_string(&components).unwrap();
857
858 let deserialized_components: Components =
859 serde_json::from_str(serialized_components.as_str()).unwrap();
860
861 assert_eq!(
862 serialized_components,
863 serde_json::to_string(&deserialized_components).unwrap()
864 )
865 }
866
867 #[test]
868 fn reserialize_deserialized_object_component() {
869 let prop = Object::new()
870 .property("name", Object::new().schema_type(BasicType::String))
871 .required("name");
872
873 let serialized_components = serde_json::to_string(&prop).unwrap();
874 let deserialized_components: Object =
875 serde_json::from_str(serialized_components.as_str()).unwrap();
876
877 assert_eq!(
878 serialized_components,
879 serde_json::to_string(&deserialized_components).unwrap()
880 )
881 }
882
883 #[test]
884 fn reserialize_deserialized_property() {
885 let prop = Object::new().schema_type(BasicType::String);
886
887 let serialized_components = serde_json::to_string(&prop).unwrap();
888 let deserialized_components: Object =
889 serde_json::from_str(serialized_components.as_str()).unwrap();
890
891 assert_eq!(
892 serialized_components,
893 serde_json::to_string(&deserialized_components).unwrap()
894 )
895 }
896
897 #[test]
898 fn serialize_deserialize_array_within_ref_or_t_object_builder() {
899 let ref_or_schema = RefOr::Type(Schema::object(Object::new().property(
900 "test",
901 RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
902 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
903 )))),
904 )));
905
906 let json_str = serde_json::to_string(&ref_or_schema).expect("");
907 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
908 let json_de_str = serde_json::to_string(&deserialized).expect("");
909 assert_eq!(json_str, json_de_str);
910 }
911
912 #[test]
913 fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
914 let ref_or_schema = RefOr::Type(Schema::object(
915 Object::new().property(
916 "test",
917 RefOr::Type(Schema::OneOf(
918 OneOf::new()
919 .item(Schema::Array(Array::new().items(RefOr::Type(
920 Schema::object(
921 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
922 ),
923 ))))
924 .item(Schema::Array(Array::new().items(RefOr::Type(
925 Schema::object(
926 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
927 ),
928 )))),
929 )),
930 ),
931 ));
932
933 let json_str = serde_json::to_string(&ref_or_schema).expect("");
934 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
935 let json_de_str = serde_json::to_string(&deserialized).expect("");
936 assert_eq!(json_str, json_de_str);
937 }
938
939 #[test]
940 fn serialize_deserialize_all_of_of_within_ref_or_t_object() {
941 let ref_or_schema = RefOr::Type(Schema::object(
942 Object::new().property(
943 "test",
944 RefOr::Type(Schema::AllOf(
945 AllOf::new()
946 .item(Schema::Array(Array::new().items(RefOr::Type(
947 Schema::object(
948 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
949 ),
950 ))))
951 .item(RefOr::Type(Schema::object(
952 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
953 ))),
954 )),
955 ),
956 ));
957
958 let json_str = serde_json::to_string(&ref_or_schema).expect("");
959 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
960 let json_de_str = serde_json::to_string(&deserialized).expect("");
961 assert_eq!(json_str, json_de_str);
962 }
963
964 #[test]
965 fn serialize_deserialize_any_of_of_within_ref_or_t_object() {
966 let ref_or_schema = RefOr::Type(Schema::object(
967 Object::new().property(
968 "test",
969 RefOr::Type(Schema::AnyOf(
970 AnyOf::new()
971 .item(Schema::Array(Array::new().items(RefOr::Type(
972 Schema::object(
973 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
974 ),
975 ))))
976 .item(RefOr::Type(Schema::object(
977 Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
978 ))),
979 )),
980 ),
981 ));
982
983 let json_str = serde_json::to_string(&ref_or_schema).expect("");
984 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
985 let json_de_str = serde_json::to_string(&deserialized).expect("");
986 assert!(json_str.contains("\"anyOf\""));
987 assert_eq!(json_str, json_de_str);
988 }
989
990 #[test]
991 fn serialize_deserialize_schema_array_ref_or_t() {
992 let ref_or_schema = RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
993 Schema::Object(Box::new(
994 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
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_eq!(json_str, json_de_str);
1002 }
1003
1004 #[test]
1005 fn serialize_deserialize_schema_array() {
1006 let ref_or_schema = Array::new().items(RefOr::Type(Schema::object(
1007 Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
1008 )));
1009
1010 let json_str = serde_json::to_string(&ref_or_schema).expect("");
1011 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
1012 let json_de_str = serde_json::to_string(&deserialized).expect("");
1013 assert_eq!(json_str, json_de_str);
1014 }
1015
1016 #[test]
1017 fn serialize_deserialize_schema_with_additional_properties() {
1018 let schema = Schema::object(Object::new().property(
1019 "map",
1020 Object::new().additional_properties(AdditionalProperties::FreeForm(true)),
1021 ));
1022
1023 let json_str = serde_json::to_string(&schema).unwrap();
1024 let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
1025 let json_de_str = serde_json::to_string(&deserialized).unwrap();
1026 assert_eq!(json_str, json_de_str);
1027 }
1028
1029 #[test]
1030 fn serialize_deserialize_schema_with_additional_properties_object() {
1031 let schema = Schema::object(Object::new().property(
1032 "map",
1033 Object::new().additional_properties(
1034 Object::new().property("name", Object::with_type(BasicType::String)),
1035 ),
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_discriminator_with_mapping() {
1046 let mut discriminator = Discriminator::new("type");
1047 discriminator.mapping = [("int".to_string(), "#/components/schemas/MyInt".to_string())]
1048 .into_iter()
1049 .collect::<PropMap<_, _>>();
1050 let one_of = OneOf::new()
1051 .item(Ref::from_schema_name("MyInt"))
1052 .discriminator(discriminator);
1053 let json_value = serde_json::to_value(one_of).unwrap();
1054
1055 assert_json_eq!(
1056 json_value,
1057 json!({
1058 "oneOf": [
1059 {
1060 "$ref": "#/components/schemas/MyInt"
1061 }
1062 ],
1063 "discriminator": {
1064 "propertyName": "type",
1065 "mapping": {
1066 "int": "#/components/schemas/MyInt"
1067 }
1068 }
1069 })
1070 );
1071 }
1072
1073 #[test]
1074 fn deserialize_reserialize_one_of_default_type() {
1075 let a = OneOf::new()
1076 .item(Schema::Array(Array::new().items(RefOr::Type(
1077 Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
1078 ))))
1079 .item(Schema::Array(Array::new().items(RefOr::Type(
1080 Schema::object(Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar")))),
1081 ))));
1082
1083 let serialized_json = serde_json::to_string(&a).expect("should serialize to json");
1084 let b: OneOf = serde_json::from_str(&serialized_json).expect("should deserialize OneOf");
1085 let reserialized_json = serde_json::to_string(&b).expect("reserialized json");
1086
1087 assert_eq!(serialized_json, reserialized_json);
1088 }
1089
1090 #[test]
1091 fn serialize_deserialize_object_with_multiple_schema_types() {
1092 let object =
1093 Object::new().schema_type(SchemaType::from_iter([BasicType::Object, BasicType::Null]));
1094
1095 let json_str = serde_json::to_string(&object).unwrap();
1096 let deserialized: Object = serde_json::from_str(&json_str).unwrap();
1097 let json_de_str = serde_json::to_string(&deserialized).unwrap();
1098 assert_eq!(json_str, json_de_str);
1099 }
1100
1101 #[test]
1102 fn test_empty_schema() {
1103 let schema = empty();
1104 assert_json_eq!(
1105 schema,
1106 json!({
1107 "default": null
1108 })
1109 )
1110 }
1111
1112 #[test]
1113 fn test_default_schema() {
1114 let schema = Schema::default();
1115 assert_json_eq!(
1116 schema,
1117 json!({
1118 "type": "object",
1119 })
1120 )
1121 }
1122
1123 #[test]
1124 fn test_ref_from_response_name() {
1125 let _ref = Ref::from_response_name("MyResponse");
1126 assert_json_eq!(
1127 _ref,
1128 json!({
1129 "$ref": "#/components/responses/MyResponse"
1130 })
1131 )
1132 }
1133
1134 #[test]
1135 fn test_additional_properties_from_ref_or() {
1136 let additional_properties =
1137 AdditionalProperties::from(RefOr::Type(Schema::Object(Box::default())));
1138 assert_json_eq!(
1139 additional_properties,
1140 json!({
1141 "type": "object",
1142 })
1143 )
1144 }
1145}