salvo_oapi/openapi/schema/
any_of.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use crate::SchemaType;
5use crate::{Array, Discriminator, PropMap, RefOr, Schema};
6
7#[non_exhaustive]
14#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
15pub struct AnyOf {
16 #[serde(rename = "anyOf")]
18 pub items: Vec<RefOr<Schema>>,
19
20 #[serde(
25 rename = "type",
26 default = "SchemaType::any",
27 skip_serializing_if = "SchemaType::is_any_value"
28 )]
29 pub schema_type: SchemaType,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub title: Option<String>,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
37 pub description: Option<String>,
38
39 #[serde(rename = "default", skip_serializing_if = "Option::is_none")]
41 pub default_value: Option<Value>,
42
43 #[serde(skip_serializing_if = "Vec::is_empty", default)]
45 pub examples: Vec<Value>,
46
47 #[serde(skip_serializing_if = "Option::is_none")]
50 pub discriminator: Option<Discriminator>,
51
52 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
54 pub extensions: PropMap<String, serde_json::Value>,
55}
56
57impl Default for AnyOf {
58 fn default() -> Self {
59 Self {
60 items: Default::default(),
61 schema_type: SchemaType::AnyValue,
62 title: None,
63 description: Default::default(),
64 default_value: Default::default(),
65 examples: Default::default(),
66 discriminator: Default::default(),
67 extensions: Default::default(),
68 }
69 }
70}
71
72impl AnyOf {
73 #[must_use]
75 pub fn new() -> Self {
76 Default::default()
77 }
78
79 #[must_use]
92 pub fn with_capacity(capacity: usize) -> Self {
93 Self {
94 items: Vec::with_capacity(capacity),
95 ..Default::default()
96 }
97 }
98 #[must_use]
102 pub fn item<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
103 self.items.push(component.into());
104 self
105 }
106
107 #[must_use]
110 pub fn schema_type<T: Into<SchemaType>>(mut self, schema_type: T) -> Self {
111 self.schema_type = schema_type.into();
112 self
113 }
114
115 #[must_use]
117 pub fn title(mut self, title: impl Into<String>) -> Self {
118 self.title = Some(title.into());
119 self
120 }
121
122 #[must_use]
124 pub fn description(mut self, description: impl Into<String>) -> Self {
125 self.description = Some(description.into());
126 self
127 }
128
129 #[must_use]
131 pub fn default_value(mut self, default: Value) -> Self {
132 self.default_value = Some(default);
133 self
134 }
135
136 #[must_use]
138 pub fn add_example<V: Into<Value>>(mut self, example: V) -> Self {
139 self.examples.push(example.into());
140 self
141 }
142
143 #[must_use]
145 pub fn discriminator(mut self, discriminator: Discriminator) -> Self {
146 self.discriminator = Some(discriminator);
147 self
148 }
149
150 #[must_use]
152 pub fn add_extension<K: Into<String>>(mut self, key: K, value: serde_json::Value) -> Self {
153 self.extensions.insert(key.into(), value);
154 self
155 }
156
157 #[must_use]
159 pub fn to_array(self) -> Array {
160 Array::new().items(self)
161 }
162}
163
164impl From<AnyOf> for Schema {
165 fn from(one_of: AnyOf) -> Self {
166 Self::AnyOf(one_of)
167 }
168}
169
170impl From<AnyOf> for RefOr<Schema> {
171 fn from(one_of: AnyOf) -> Self {
172 Self::Type(Schema::AnyOf(one_of))
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use assert_json_diff::assert_json_eq;
179 use serde_json::json;
180
181 use super::*;
182
183 #[test]
184 fn test_build_any_of() {
185 let any_of = AnyOf::with_capacity(5)
186 .title("title")
187 .description("description")
188 .default_value(Value::String("default".to_owned()))
189 .add_example(Value::String("example1".to_owned()))
190 .add_example(Value::String("example2".to_owned()))
191 .discriminator(Discriminator::new("discriminator".to_owned()));
192
193 assert_eq!(any_of.items.len(), 0);
194 assert_eq!(any_of.items.capacity(), 5);
195 assert_json_eq!(
196 any_of,
197 json!({
198 "anyOf": [],
199 "title": "title",
200 "description": "description",
201 "default": "default",
202 "examples": ["example1", "example2"],
203 "discriminator": {
204 "propertyName": "discriminator"
205 }
206 })
207 )
208 }
209
210 #[test]
211 fn test_schema_from_any_of() {
212 let any_of = AnyOf::new();
213 let schema = Schema::from(any_of);
214 assert_json_eq!(
215 schema,
216 json!({
217 "anyOf": []
218 })
219 )
220 }
221
222 #[test]
223 fn test_refor_schema_from_any_of() {
224 let any_of = AnyOf::new();
225 let ref_or: RefOr<Schema> = RefOr::from(any_of);
226 assert_json_eq!(
227 ref_or,
228 json!({
229 "anyOf": []
230 })
231 )
232 }
233
234 #[test]
235 fn test_anyof_with_extensions() {
236 let expected = json!("value");
237 let json_value = AnyOf::new().add_extension("x-some-extension", expected.clone());
238
239 let value = serde_json::to_value(&json_value).unwrap();
240 assert_eq!(value.get("x-some-extension"), Some(&expected));
241 }
242}