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