mod all_of;
mod any_of;
mod array;
mod number;
mod object;
mod one_of;
use std::ops::{Deref, DerefMut};
pub use all_of::AllOf;
pub use any_of::AnyOf;
pub use array::{Array, ArrayItems};
pub use number::Number;
pub use object::Object;
pub use one_of::OneOf;
use serde::{Deserialize, Serialize};
use crate::{PropMap, RefOr};
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Schemas(pub PropMap<String, RefOr<Schema>>);
impl<K, R> From<PropMap<K, R>> for Schemas
where
K: Into<String>,
R: Into<RefOr<Schema>>,
{
fn from(inner: PropMap<K, R>) -> Self {
Self(
inner
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect(),
)
}
}
impl<K, R, const N: usize> From<[(K, R); N]> for Schemas
where
K: Into<String>,
R: Into<RefOr<Schema>>,
{
fn from(inner: [(K, R); N]) -> Self {
Self(
<[(K, R)]>::into_vec(Box::new(inner))
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect(),
)
}
}
impl Deref for Schemas {
type Target = PropMap<String, RefOr<Schema>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Schemas {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl IntoIterator for Schemas {
type Item = (String, RefOr<Schema>);
type IntoIter = <PropMap<String, RefOr<Schema>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Schemas {
#[must_use]
pub fn new() -> Self {
Default::default()
}
#[must_use]
pub fn schema<K: Into<String>, V: Into<RefOr<Schema>>>(mut self, key: K, value: V) -> Self {
self.insert(key, value);
self
}
pub fn insert<K: Into<String>, V: Into<RefOr<Schema>>>(&mut self, key: K, value: V) {
self.0.insert(key.into(), value.into());
}
pub fn append(&mut self, other: &mut Self) {
let items = std::mem::take(&mut other.0);
for item in items {
self.insert(item.0, item.1);
}
}
pub fn extend<I, K, V>(&mut self, iter: I)
where
I: IntoIterator<Item = (K, V)>,
K: Into<String>,
V: Into<RefOr<Schema>>,
{
for (k, v) in iter.into_iter() {
self.insert(k, v);
}
}
}
#[must_use]
pub fn empty() -> Schema {
Schema::object(
Object::new()
.schema_type(SchemaType::AnyValue)
.default_value(serde_json::Value::Null),
)
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(untagged, rename_all = "camelCase")]
pub enum Schema {
Array(Array),
Object(Box<Object>),
OneOf(OneOf),
AllOf(AllOf),
AnyOf(AnyOf),
}
impl Default for Schema {
fn default() -> Self {
Self::Object(Default::default())
}
}
impl Schema {
#[must_use]
pub fn object(obj: Object) -> Self {
Self::Object(Box::new(obj))
}
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct Discriminator {
pub property_name: String,
#[serde(skip_serializing_if = "PropMap::is_empty", default)]
pub mapping: PropMap<String, String>,
#[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
pub extensions: PropMap<String, serde_json::Value>,
}
impl Discriminator {
pub fn new<I: Into<String>>(property_name: I) -> Self {
Self {
property_name: property_name.into(),
mapping: PropMap::new(),
extensions: PropMap::new(),
}
}
#[must_use]
pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
self.extensions = extensions;
self
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_false(value: &bool) -> bool {
!*value
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(untagged)]
pub enum AdditionalProperties<T> {
RefOr(RefOr<T>),
FreeForm(bool),
}
impl<T> From<RefOr<T>> for AdditionalProperties<T> {
fn from(value: RefOr<T>) -> Self {
Self::RefOr(value)
}
}
impl From<Object> for AdditionalProperties<Schema> {
fn from(value: Object) -> Self {
Self::RefOr(RefOr::Type(Schema::object(value)))
}
}
impl From<Array> for AdditionalProperties<Schema> {
fn from(value: Array) -> Self {
Self::RefOr(RefOr::Type(Schema::Array(value)))
}
}
impl From<Ref> for AdditionalProperties<Schema> {
fn from(value: Ref) -> Self {
Self::RefOr(RefOr::Ref(value))
}
}
impl From<OneOf> for AdditionalProperties<Schema> {
fn from(value: OneOf) -> Self {
Self::RefOr(RefOr::Type(Schema::OneOf(value)))
}
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
pub struct Ref {
#[serde(rename = "$ref")]
pub ref_location: String,
#[serde(skip_serializing_if = "String::is_empty", default)]
pub description: String,
#[serde(skip_serializing_if = "String::is_empty", default)]
pub summary: String,
}
impl Ref {
#[must_use]
pub fn new<I: Into<String>>(ref_location: I) -> Self {
Self {
ref_location: ref_location.into(),
..Default::default()
}
}
#[must_use]
pub fn from_schema_name<I: Into<String>>(schema_name: I) -> Self {
Self::new(format!("#/components/schemas/{}", schema_name.into()))
}
#[must_use]
pub fn from_response_name<I: Into<String>>(response_name: I) -> Self {
Self::new(format!("#/components/responses/{}", response_name.into()))
}
#[must_use]
pub fn ref_location(mut self, ref_location: String) -> Self {
self.ref_location = ref_location;
self
}
#[must_use]
pub fn ref_location_from_schema_name<S: Into<String>>(mut self, schema_name: S) -> Self {
self.ref_location = format!("#/components/schemas/{}", schema_name.into());
self
}
#[must_use]
pub fn description<S: Into<String>>(mut self, description: S) -> Self {
self.description = description.into();
self
}
#[must_use]
pub fn summary<S: Into<String>>(mut self, summary: S) -> Self {
self.summary = summary.into();
self
}
#[must_use]
pub fn to_array(self) -> Array {
Array::new().items(self)
}
}
impl From<Ref> for RefOr<Schema> {
fn from(r: Ref) -> Self {
Self::Ref(r)
}
}
impl<T> From<T> for RefOr<T> {
fn from(t: T) -> Self {
Self::Type(t)
}
}
impl Default for RefOr<Schema> {
fn default() -> Self {
Self::Type(Schema::object(Object::new()))
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(untagged)]
pub enum SchemaType {
Basic(BasicType),
Array(Vec<BasicType>),
AnyValue,
}
impl Default for SchemaType {
fn default() -> Self {
Self::Basic(BasicType::default())
}
}
impl From<BasicType> for SchemaType {
fn from(value: BasicType) -> Self {
Self::basic(value)
}
}
impl FromIterator<BasicType> for SchemaType {
fn from_iter<T: IntoIterator<Item = BasicType>>(iter: T) -> Self {
Self::Array(iter.into_iter().collect())
}
}
impl SchemaType {
#[must_use]
pub fn basic(r#type: BasicType) -> Self {
Self::Basic(r#type)
}
#[must_use]
pub fn any() -> Self {
Self::AnyValue
}
#[must_use]
pub fn is_any_value(&self) -> bool {
matches!(self, Self::AnyValue)
}
}
#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum BasicType {
#[default]
Object,
String,
Integer,
Number,
Boolean,
Array,
Null,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase", untagged)]
pub enum SchemaFormat {
KnownFormat(KnownFormat),
Custom(String),
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum KnownFormat {
Int8,
Int16,
Int32,
Int64,
#[serde(rename = "uint8")]
UInt8,
#[serde(rename = "uint16")]
UInt16,
#[serde(rename = "uint32")]
UInt32,
#[serde(rename = "uint64")]
UInt64,
Float,
Double,
Byte,
Binary,
Time,
Date,
DateTime,
Duration,
Password,
String,
#[cfg(any(feature = "decimal", feature = "decimal-float"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "decimal", feature = "decimal-float"))))]
Decimal,
#[cfg(feature = "ulid")]
#[cfg_attr(docsrs, doc(cfg(feature = "ulid")))]
Ulid,
#[cfg(feature = "uuid")]
#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
Uuid,
#[cfg(feature = "url")]
#[cfg_attr(docsrs, doc(cfg(feature = "url")))]
Url,
#[cfg(feature = "url")]
#[cfg_attr(docsrs, doc(cfg(feature = "url")))]
UriReference,
#[cfg(feature = "url")]
#[cfg_attr(docsrs, doc(cfg(feature = "url")))]
Iri,
#[cfg(feature = "url")]
#[cfg_attr(docsrs, doc(cfg(feature = "url")))]
IriReference,
Email,
IdnEmail,
Hostname,
IdnHostname,
Ipv4,
Ipv6,
UriTemplate,
JsonPointer,
RelativeJsonPointer,
Regex,
}
#[cfg(test)]
mod tests {
use assert_json_diff::assert_json_eq;
use serde_json::{Value, json};
use super::*;
use crate::*;
#[test]
fn create_schema_serializes_json() -> Result<(), serde_json::Error> {
let openapi = OpenApi::new("My api", "1.0.0").components(
Components::new()
.add_schema("Person", Ref::new("#/components/PersonModel"))
.add_schema(
"Credential",
Schema::from(
Object::new()
.property(
"id",
Object::new()
.schema_type(BasicType::Integer)
.format(SchemaFormat::KnownFormat(KnownFormat::Int32))
.description("Id of credential")
.default_value(json!(1i32)),
)
.property(
"name",
Object::new()
.schema_type(BasicType::String)
.description("Name of credential"),
)
.property(
"status",
Object::new()
.schema_type(BasicType::String)
.default_value(json!("Active"))
.description("Credential status")
.enum_values(["Active", "NotActive", "Locked", "Expired"]),
)
.property(
"history",
Array::new().items(Ref::from_schema_name("UpdateHistory")),
)
.property("tags", Object::with_type(BasicType::String).to_array()),
),
),
);
let serialized = serde_json::to_string_pretty(&openapi)?;
println!("serialized json:\n {serialized}");
let value = serde_json::to_value(&openapi)?;
let credential = get_json_path(&value, "components.schemas.Credential.properties");
let person = get_json_path(&value, "components.schemas.Person");
assert!(
credential.get("id").is_some(),
"could not find path: components.schemas.Credential.properties.id"
);
assert!(
credential.get("status").is_some(),
"could not find path: components.schemas.Credential.properties.status"
);
assert!(
credential.get("name").is_some(),
"could not find path: components.schemas.Credential.properties.name"
);
assert!(
credential.get("history").is_some(),
"could not find path: components.schemas.Credential.properties.history"
);
assert_json_eq!(
credential
.get("id")
.unwrap_or(&serde_json::value::Value::Null),
json!({"type":"integer","format":"int32","description":"Id of credential","default":1})
);
assert_json_eq!(
credential
.get("name")
.unwrap_or(&serde_json::value::Value::Null),
json!({"type":"string","description":"Name of credential"})
);
assert_json_eq!(
credential
.get("status")
.unwrap_or(&serde_json::value::Value::Null),
json!({"default":"Active","description":"Credential status","enum":["Active","NotActive","Locked","Expired"],"type":"string"})
);
assert_json_eq!(
credential
.get("history")
.unwrap_or(&serde_json::value::Value::Null),
json!({"items":{"$ref":"#/components/schemas/UpdateHistory"},"type":"array"})
);
assert_eq!(person, &json!({"$ref":"#/components/PersonModel"}));
Ok(())
}
#[test]
fn test_property_order() {
let json_value = Object::new()
.property(
"id",
Object::new()
.schema_type(BasicType::Integer)
.format(SchemaFormat::KnownFormat(KnownFormat::Int32))
.description("Id of credential")
.default_value(json!(1i32)),
)
.property(
"name",
Object::new()
.schema_type(BasicType::String)
.description("Name of credential"),
)
.property(
"status",
Object::new()
.schema_type(BasicType::String)
.default_value(json!("Active"))
.description("Credential status")
.enum_values(["Active", "NotActive", "Locked", "Expired"]),
)
.property(
"history",
Array::new().items(Ref::from_schema_name("UpdateHistory")),
)
.property("tags", Object::with_type(BasicType::String).to_array());
#[cfg(not(feature = "preserve-order"))]
assert_eq!(
json_value.properties.keys().collect::<Vec<_>>(),
vec!["history", "id", "name", "status", "tags"]
);
#[cfg(feature = "preserve-order")]
assert_eq!(
json_value.properties.keys().collect::<Vec<_>>(),
vec!["id", "name", "status", "history", "tags"]
);
}
#[test]
fn test_additional_properties() {
let json_value =
Object::new().additional_properties(Object::new().schema_type(BasicType::String));
assert_json_eq!(
json_value,
json!({
"type": "object",
"additionalProperties": {
"type": "string"
}
})
);
let json_value = Object::new().additional_properties(
Array::new().items(Object::new().schema_type(BasicType::Number)),
);
assert_json_eq!(
json_value,
json!({
"type": "object",
"additionalProperties": {
"items": {
"type": "number",
},
"type": "array",
}
})
);
let json_value = Object::new().additional_properties(Ref::from_schema_name("ComplexModel"));
assert_json_eq!(
json_value,
json!({
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/ComplexModel"
}
})
)
}
#[test]
fn test_object_with_name() {
let json_value = Object::new().name("SomeName");
assert_json_eq!(
json_value,
json!({
"type": "object",
"name": "SomeName"
})
);
}
#[test]
fn test_derive_object_with_examples() {
let expected = r#"{"type":"object","examples":[{"age":20,"name":"bob the cat"}]}"#;
let json_value = Object::new().examples([json!({"age": 20, "name": "bob the cat"})]);
let value_string = serde_json::to_string(&json_value).unwrap();
assert_eq!(
value_string, expected,
"value string != expected string, {value_string} != {expected}"
);
}
fn get_json_path<'a>(value: &'a Value, path: &str) -> &'a Value {
path.split('.').fold(value, |acc, fragment| {
acc.get(fragment).unwrap_or(&serde_json::value::Value::Null)
})
}
#[test]
fn test_array_new() {
let array = Array::new().items(
Object::new().property(
"id",
Object::new()
.schema_type(BasicType::Integer)
.format(SchemaFormat::KnownFormat(KnownFormat::Int32))
.description("Id of credential")
.default_value(json!(1i32)),
),
);
assert!(matches!(
array.schema_type,
SchemaType::Basic(BasicType::Array)
));
}
#[test]
fn test_array_builder() {
let array: Array = Array::new().items(
Object::new().property(
"id",
Object::new()
.schema_type(BasicType::Integer)
.format(SchemaFormat::KnownFormat(KnownFormat::Int32))
.description("Id of credential")
.default_value(json!(1i32)),
),
);
assert!(matches!(
array.schema_type,
SchemaType::Basic(BasicType::Array)
));
}
#[test]
fn reserialize_deserialized_schema_components() {
let components = Components::new()
.extend_schemas(vec![(
"Comp",
Schema::from(
Object::new()
.property("name", Object::new().schema_type(BasicType::String))
.required("name"),
),
)])
.response("204", Response::new("No Content"))
.extend_responses(vec![("200", Response::new("Okay"))])
.add_security_scheme("TLS", SecurityScheme::MutualTls { description: None })
.extend_security_schemes(vec![(
"APIKey",
SecurityScheme::Http(security::Http::default()),
)]);
let serialized_components = serde_json::to_string(&components).unwrap();
let deserialized_components: Components =
serde_json::from_str(serialized_components.as_str()).unwrap();
assert_eq!(
serialized_components,
serde_json::to_string(&deserialized_components).unwrap()
)
}
#[test]
fn reserialize_deserialized_object_component() {
let prop = Object::new()
.property("name", Object::new().schema_type(BasicType::String))
.required("name");
let serialized_components = serde_json::to_string(&prop).unwrap();
let deserialized_components: Object =
serde_json::from_str(serialized_components.as_str()).unwrap();
assert_eq!(
serialized_components,
serde_json::to_string(&deserialized_components).unwrap()
)
}
#[test]
fn reserialize_deserialized_property() {
let prop = Object::new().schema_type(BasicType::String);
let serialized_components = serde_json::to_string(&prop).unwrap();
let deserialized_components: Object =
serde_json::from_str(serialized_components.as_str()).unwrap();
assert_eq!(
serialized_components,
serde_json::to_string(&deserialized_components).unwrap()
)
}
#[test]
fn serialize_deserialize_array_within_ref_or_t_object_builder() {
let ref_or_schema = RefOr::Type(Schema::object(Object::new().property(
"test",
RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
)))),
)));
let json_str = serde_json::to_string(&ref_or_schema).expect("");
let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
let json_de_str = serde_json::to_string(&deserialized).expect("");
assert_eq!(json_str, json_de_str);
}
#[test]
fn serialize_deserialize_one_of_within_ref_or_t_object_builder() {
let ref_or_schema = RefOr::Type(Schema::object(
Object::new().property(
"test",
RefOr::Type(Schema::OneOf(
OneOf::new()
.item(Schema::Array(Array::new().items(RefOr::Type(
Schema::object(
Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
),
))))
.item(Schema::Array(Array::new().items(RefOr::Type(
Schema::object(
Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
),
)))),
)),
),
));
let json_str = serde_json::to_string(&ref_or_schema).expect("");
let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
let json_de_str = serde_json::to_string(&deserialized).expect("");
assert_eq!(json_str, json_de_str);
}
#[test]
fn serialize_deserialize_all_of_of_within_ref_or_t_object() {
let ref_or_schema = RefOr::Type(Schema::object(
Object::new().property(
"test",
RefOr::Type(Schema::AllOf(
AllOf::new()
.item(Schema::Array(Array::new().items(RefOr::Type(
Schema::object(
Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
),
))))
.item(RefOr::Type(Schema::object(
Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
))),
)),
),
));
let json_str = serde_json::to_string(&ref_or_schema).expect("");
let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
let json_de_str = serde_json::to_string(&deserialized).expect("");
assert_eq!(json_str, json_de_str);
}
#[test]
fn serialize_deserialize_any_of_of_within_ref_or_t_object() {
let ref_or_schema = RefOr::Type(Schema::object(
Object::new().property(
"test",
RefOr::Type(Schema::AnyOf(
AnyOf::new()
.item(Schema::Array(Array::new().items(RefOr::Type(
Schema::object(
Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
),
))))
.item(RefOr::Type(Schema::object(
Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar"))),
))),
)),
),
));
let json_str = serde_json::to_string(&ref_or_schema).expect("");
let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
let json_de_str = serde_json::to_string(&deserialized).expect("");
assert!(json_str.contains("\"anyOf\""));
assert_eq!(json_str, json_de_str);
}
#[test]
fn serialize_deserialize_schema_array_ref_or_t() {
let ref_or_schema = RefOr::Type(Schema::Array(Array::new().items(RefOr::Type(
Schema::Object(Box::new(
Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
)),
))));
let json_str = serde_json::to_string(&ref_or_schema).expect("");
let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
let json_de_str = serde_json::to_string(&deserialized).expect("");
assert_eq!(json_str, json_de_str);
}
#[test]
fn serialize_deserialize_schema_array() {
let ref_or_schema = Array::new().items(RefOr::Type(Schema::object(
Object::new().property("element", RefOr::Ref(Ref::new("#/test"))),
)));
let json_str = serde_json::to_string(&ref_or_schema).expect("");
let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).expect("");
let json_de_str = serde_json::to_string(&deserialized).expect("");
assert_eq!(json_str, json_de_str);
}
#[test]
fn serialize_deserialize_schema_with_additional_properties() {
let schema = Schema::object(Object::new().property(
"map",
Object::new().additional_properties(AdditionalProperties::FreeForm(true)),
));
let json_str = serde_json::to_string(&schema).unwrap();
let deserialized: RefOr<Schema> = serde_json::from_str(&json_str).unwrap();
let json_de_str = serde_json::to_string(&deserialized).unwrap();
assert_eq!(json_str, json_de_str);
}
#[test]
fn serialize_deserialize_schema_with_additional_properties_object() {
let schema = Schema::object(Object::new().property(
"map",
Object::new().additional_properties(
Object::new().property("name", Object::with_type(BasicType::String)),
),
));
let json_str = serde_json::to_string(&schema).expect("serde json should success");
let deserialized: RefOr<Schema> =
serde_json::from_str(&json_str).expect("serde json should success");
let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
assert_eq!(json_str, json_de_str);
}
#[test]
fn serialize_discriminator_with_mapping() {
let mut discriminator = Discriminator::new("type");
discriminator.mapping = [("int".to_owned(), "#/components/schemas/MyInt".to_owned())]
.into_iter()
.collect::<PropMap<_, _>>();
let one_of = OneOf::new()
.item(Ref::from_schema_name("MyInt"))
.discriminator(discriminator);
let json_value = serde_json::to_value(one_of).expect("serde json should success");
assert_json_eq!(
json_value,
json!({
"oneOf": [
{
"$ref": "#/components/schemas/MyInt"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"int": "#/components/schemas/MyInt"
}
}
})
);
}
#[test]
fn deserialize_reserialize_one_of_default_type() {
let a = OneOf::new()
.item(Schema::Array(Array::new().items(RefOr::Type(
Schema::object(Object::new().property("element", RefOr::Ref(Ref::new("#/test")))),
))))
.item(Schema::Array(Array::new().items(RefOr::Type(
Schema::object(Object::new().property("foobar", RefOr::Ref(Ref::new("#/foobar")))),
))));
let serialized_json = serde_json::to_string(&a).expect("should serialize to json");
let b: OneOf = serde_json::from_str(&serialized_json).expect("should deserialize OneOf");
let reserialized_json = serde_json::to_string(&b).expect("reserialized json");
assert_eq!(serialized_json, reserialized_json);
}
#[test]
fn serialize_deserialize_object_with_multiple_schema_types() {
let object =
Object::new().schema_type(SchemaType::from_iter([BasicType::Object, BasicType::Null]));
let json_str = serde_json::to_string(&object).expect("serde json should success");
let deserialized: Object =
serde_json::from_str(&json_str).expect("serde json should success");
let json_de_str = serde_json::to_string(&deserialized).expect("serde json should success");
assert_eq!(json_str, json_de_str);
}
#[test]
fn test_empty_schema() {
let schema = empty();
assert_json_eq!(
schema,
json!({
"default": null
})
)
}
#[test]
fn test_default_schema() {
let schema = Schema::default();
assert_json_eq!(
schema,
json!({
"type": "object",
})
)
}
#[test]
fn test_ref_from_response_name() {
let _ref = Ref::from_response_name("MyResponse");
assert_json_eq!(
_ref,
json!({
"$ref": "#/components/responses/MyResponse"
})
)
}
#[test]
fn test_additional_properties_from_ref_or() {
let additional_properties =
AdditionalProperties::from(RefOr::Type(Schema::Object(Box::default())));
assert_json_eq!(
additional_properties,
json!({
"type": "object",
})
)
}
}