Skip to content

Commit

Permalink
oapi: Add extensions for schemas (#846)
Browse files Browse the repository at this point in the history
* oapi: Add extensions for schemas

* wip

* wip

* fix

* fmt
  • Loading branch information
chrislearn authored Aug 6, 2024
1 parent 401787d commit d6a8186
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 6 deletions.
21 changes: 20 additions & 1 deletion crates/oapi/src/openapi/schema/all_of.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{Discriminator, RefOr, Schema};
use crate::{Discriminator, PropMap, RefOr, Schema};

/// AllOf [Composite Object][allof] component holds
/// multiple components together where API endpoint will return a combination of all of them.
Expand Down Expand Up @@ -40,6 +40,10 @@ pub struct AllOf {
/// Set `true` to allow `"null"` to be used as value for given type.
#[serde(default, skip_serializing_if = "super::is_false")]
pub nullable: bool,

/// Optional extensions `x-something`.
#[serde(skip_serializing_if = "Option::is_none", flatten)]
pub extensions: Option<PropMap<String, serde_json::Value>>,
}

impl AllOf {
Expand Down Expand Up @@ -110,6 +114,12 @@ impl AllOf {
self.nullable = nullable;
self
}

/// Add openapi extensions (`x-something`) for [`AllOf`].
pub fn extensions(mut self, extensions: Option<PropMap<String, serde_json::Value>>) -> Self {
self.extensions = extensions;
self
}
}

impl From<AllOf> for Schema {
Expand Down Expand Up @@ -182,4 +192,13 @@ mod tests {
})
)
}

#[test]
fn test_allof_with_extensions() {
let expected = json!("value");
let json_value = AllOf::new().extensions(Some([("x-some-extension".to_string(), expected.clone())].into()));

let value = serde_json::to_value(&json_value).unwrap();
assert_eq!(value.get("x-some-extension"), Some(&expected));
}
}
21 changes: 20 additions & 1 deletion crates/oapi/src/openapi/schema/any_of.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{Discriminator, RefOr, Schema};
use crate::{Discriminator, PropMap, RefOr, Schema};

/// AnyOf [Composite Object][allof] component holds
/// multiple components together where API endpoint will return a combination of all of them.
Expand Down Expand Up @@ -40,6 +40,10 @@ pub struct AnyOf {
/// Set `true` to allow `"null"` to be used as value for given type.
#[serde(default, skip_serializing_if = "super::is_false")]
pub nullable: bool,

/// Optional extensions `x-something`.
#[serde(skip_serializing_if = "Option::is_none", flatten)]
pub extensions: Option<PropMap<String, serde_json::Value>>,
}

impl AnyOf {
Expand Down Expand Up @@ -110,6 +114,12 @@ impl AnyOf {
self.nullable = nullable;
self
}

/// Add openapi extensions (`x-something`) for [`AnyOf`].
pub fn extensions(mut self, extensions: Option<PropMap<String, serde_json::Value>>) -> Self {
self.extensions = extensions;
self
}
}

impl From<AnyOf> for Schema {
Expand Down Expand Up @@ -182,4 +192,13 @@ mod tests {
})
)
}

#[test]
fn test_anyof_with_extensions() {
let expected = json!("value");
let json_value = AnyOf::new().extensions(Some([("x-some-extension".to_string(), expected.clone())].into()));

let value = serde_json::to_value(&json_value).unwrap();
assert_eq!(value.get("x-some-extension"), Some(&expected));
}
}
26 changes: 23 additions & 3 deletions crates/oapi/src/openapi/schema/array.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{Deprecated, RefOr, Schema, SchemaType, Xml};
use crate::{Deprecated, PropMap, RefOr, Schema, SchemaType, Xml};

/// Array represents [`Vec`] or [`slice`] type of items.
///
Expand Down Expand Up @@ -57,6 +57,10 @@ pub struct Array {
/// Set `true` to allow `"null"` to be used as value for given type.
#[serde(default, skip_serializing_if = "super::is_false")]
pub nullable: bool,

/// Optional extensions `x-something`.
#[serde(skip_serializing_if = "Option::is_none", flatten)]
pub extensions: Option<PropMap<String, serde_json::Value>>,
}

impl Default for Array {
Expand All @@ -74,6 +78,7 @@ impl Default for Array {
min_items: Default::default(),
xml: Default::default(),
nullable: Default::default(),
extensions: Default::default(),
}
}
}
Expand All @@ -88,9 +93,9 @@ impl Array {
/// # use salvo_oapi::schema::{Schema, Array, SchemaType, Object};
/// let string_array = Array::new(Object::with_type(SchemaType::String));
/// ```
pub fn new<I: Into<RefOr<Schema>>>(component: I) -> Self {
pub fn new<I: Into<RefOr<Schema>>>(items: I) -> Self {
Self {
items: Box::new(component.into()),
items: Box::new(items.into()),
..Default::default()
}
}
Expand Down Expand Up @@ -159,6 +164,12 @@ impl Array {
self.nullable = nullable;
self
}

/// Add openapi extensions (`x-something`) for [`Array`].
pub fn extensions(mut self, extensions: Option<PropMap<String, serde_json::Value>>) -> Self {
self.extensions = extensions;
self
}
}

impl From<Array> for Schema {
Expand Down Expand Up @@ -244,4 +255,13 @@ mod tests {
})
)
}

#[test]
fn test_array_with_extensions() {
let expected = json!("value");
let json_value = Array::default().extensions(Some([("x-some-extension".to_string(), expected.clone())].into()));

let value = serde_json::to_value(&json_value).unwrap();
assert_eq!(value.get("x-some-extension"), Some(&expected));
}
}
19 changes: 19 additions & 0 deletions crates/oapi/src/openapi/schema/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ pub struct Object {
/// `0` will have same effect as omitting the attribute.
#[serde(skip_serializing_if = "Option::is_none")]
pub min_properties: Option<usize>,

/// Optional extensions `x-something`.
#[serde(skip_serializing_if = "Option::is_none", flatten)]
pub extensions: Option<PropMap<String, serde_json::Value>>,
}

impl Object {
Expand Down Expand Up @@ -312,6 +316,12 @@ impl Object {
self.min_properties = Some(min_properties);
self
}

/// Add openapi extensions (`x-something`) for [`Object`].
pub fn extensions(mut self, extensions: Option<PropMap<String, serde_json::Value>>) -> Self {
self.extensions = extensions;
self
}
}

impl From<Object> for Schema {
Expand Down Expand Up @@ -417,4 +427,13 @@ mod tests {
})
);
}

#[test]
fn test_object_with_extensions() {
let expected = json!("value");
let json_value = Object::new().extensions(Some([("x-some-extension".to_string(), expected.clone())].into()));

let value = serde_json::to_value(&json_value).unwrap();
assert_eq!(value.get("x-some-extension"), Some(&expected));
}
}
21 changes: 20 additions & 1 deletion crates/oapi/src/openapi/schema/one_of.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{Discriminator, RefOr, Schema};
use crate::{Discriminator, PropMap, RefOr, Schema};

/// OneOf [Composite Object][oneof] component holds
/// multiple components together where API endpoint could return any of them.
Expand Down Expand Up @@ -40,6 +40,10 @@ pub struct OneOf {
/// Set `true` to allow `"null"` to be used as value for given type.
#[serde(default, skip_serializing_if = "super::is_false")]
pub nullable: bool,

/// Optional extensions `x-something`.
#[serde(skip_serializing_if = "Option::is_none", flatten)]
pub extensions: Option<PropMap<String, serde_json::Value>>,
}

impl OneOf {
Expand Down Expand Up @@ -110,6 +114,12 @@ impl OneOf {
self.nullable = nullable;
self
}

/// Add openapi extensions (`x-something`) for [`OneOf`].
pub fn extensions(mut self, extensions: Option<PropMap<String, serde_json::Value>>) -> Self {
self.extensions = extensions;
self
}
}

impl From<OneOf> for Schema {
Expand Down Expand Up @@ -182,4 +192,13 @@ mod tests {
})
)
}

#[test]
fn test_oneof_with_extensions() {
let expected = json!("value");
let json_value = OneOf::new().extensions(Some([("x-some-extension".to_string(), expected.clone())].into()));

let value = serde_json::to_value(&json_value).unwrap();
assert_eq!(value.get("x-some-extension"), Some(&expected));
}
}

0 comments on commit d6a8186

Please sign in to comment.