1mod macros;
2mod r#ref;
3mod schema;
4
5use std::{
6 collections::{BTreeMap, btree_map},
7 ops::{Deref, DerefMut},
8};
9
10use http::Method;
11use serde::{Deserialize, Serialize, ser::SerializeMap};
12use serde_json::Value;
13
14pub use self::{r#ref::*, schema::*};
15use crate::private::{is_default, merge_maps};
16
17pub type Map<K, V> = BTreeMap<K, V>;
18pub type Entry<'a, K, V> = btree_map::Entry<'a, K, V>;
19
20macros::define_openapi_spec_object! {
21 pub struct OpenApi {
22 pub openapi: String,
23 pub info: Info,
24 pub json_schema_dialect: Option<String>,
25 #[serde(default, skip_serializing_if = "Vec::is_empty")]
26 pub servers: Vec<Server>,
27 #[serde(default, skip_serializing_if = "is_default")]
28 pub paths: Paths,
29 #[serde(default, skip_serializing_if = "Map::is_empty")]
30 pub webhooks: Map<String, PathItem>,
31 #[serde(default, skip_serializing_if = "is_default")]
32 pub components: Components,
33 pub security: Option<Vec<SecurityRequirement>>,
34 #[serde(default, skip_serializing_if = "Vec::is_empty")]
35 pub tags: Vec<Tag>,
36 pub external_docs: Option<ExternalDocs>,
37
38 #[serde(flatten)]
39 pub extensions: Extensions,
40 }
41}
42
43impl OpenApi {
44 pub const DEFAULT_VERSION: &str = "3.1.0";
45
46 pub fn new(version: String, info: Info) -> Self {
47 Self {
48 openapi: version,
49 info,
50 json_schema_dialect: Default::default(),
51 servers: Default::default(),
52 paths: Default::default(),
53 webhooks: Default::default(),
54 components: Default::default(),
55 security: Default::default(),
56 tags: Default::default(),
57 external_docs: Default::default(),
58 extensions: Default::default(),
59 }
60 }
61
62 pub fn operations_mut(&mut self) -> impl Iterator<Item = &mut Operation> {
63 self.paths
64 .paths
65 .values_mut()
66 .flat_map(|item| item.operations_mut())
67 }
68}
69
70impl Default for OpenApi {
71 fn default() -> Self {
72 Self::new(Self::DEFAULT_VERSION.to_owned(), Info::default())
73 }
74}
75
76macros::define_openapi_spec_object! {
77 #[derive(Default)]
78 pub struct Info {
79 pub title: String,
80 pub summary: Option<String>,
81 pub description: Option<String>,
82 pub terms_of_service: Option<String>,
83 pub contact: Option<Contact>,
84 pub license: Option<License>,
85 pub version: String,
86
87 #[serde(flatten)]
88 pub extensions: Extensions,
89 }
90}
91
92impl Info {
93 pub fn new(title: String) -> Self {
94 Self::default().with_title(title)
95 }
96}
97
98#[macro_export]
99macro_rules! info_from_env {
100 () => {
101 $crate::openapi::Info::default()
102 .with_title(env!("CARGO_PKG_NAME"))
103 .with_version(env!("CARGO_PKG_VERSION"))
104 .with_maybe_description(option_env!("CARGO_PKG_DESCRIPTION").map(ToOwned::to_owned))
105 .with_maybe_license(option_env!("CARGO_PKG_LICENSE").map(|license| {
106 $crate::openapi::License::new(license.to_owned())
107 .with_identifier(license.to_owned())
108 }))
109 };
110}
111
112macros::define_openapi_spec_object! {
113 #[derive(Default)]
114 pub struct Contact {
115 pub name: Option<String>,
116 pub url: Option<String>,
117 pub email: Option<String>,
118
119 #[serde(flatten)]
120 pub extensions: Extensions,
121 }
122}
123
124macros::define_openapi_spec_object! {
125 pub struct License {
126 pub name: String,
127 pub identifier: Option<String>,
128 pub url: Option<String>,
129
130 #[serde(flatten)]
131 pub extensions: Extensions,
132 }
133}
134
135impl License {
136 pub fn new(name: String) -> Self {
137 Self {
138 name,
139 identifier: Default::default(),
140 url: Default::default(),
141 extensions: Default::default(),
142 }
143 }
144}
145
146macros::define_openapi_spec_object! {
147 pub struct Server {
148 pub url: String,
149 pub description: Option<String>,
150 #[serde(default, skip_serializing_if = "Map::is_empty")]
151 pub variables: Map<String, ServerVariable>,
152
153 #[serde(flatten)]
154 pub extensions: Extensions,
155 }
156}
157
158impl Server {
159 pub fn new(url: String) -> Self {
160 Server {
161 url,
162 description: Default::default(),
163 variables: Default::default(),
164 extensions: Default::default(),
165 }
166 }
167}
168
169macros::define_openapi_spec_object! {
170 pub struct ServerVariable {
171 pub r#enum: Vec<String>,
172 pub default: String,
173 pub description: Option<String>,
174
175 #[serde(flatten)]
176 pub extensions: Extensions,
177 }
178}
179
180impl ServerVariable {
181 pub fn new(r#enum: Vec<String>, default: String) -> Self {
182 Self {
183 r#enum,
184 default,
185 description: Default::default(),
186 extensions: Default::default(),
187 }
188 }
189}
190
191macros::define_openapi_spec_object! {
192 #[derive(Default)]
193 pub struct Components {
194 #[serde(default, skip_serializing_if = "Map::is_empty")]
195 pub schemas: Map<String, MaybeRef<Schema>>,
196 #[serde(default, skip_serializing_if = "Map::is_empty")]
197 pub responses: Map<String, MaybeRef<Response>>,
198 #[serde(default, skip_serializing_if = "Map::is_empty")]
199 pub parameters: Map<String, MaybeRef<Parameter>>,
200 #[serde(default, skip_serializing_if = "Map::is_empty")]
201 pub examples: Map<String, MaybeRef<Parameter>>,
202 #[serde(default, skip_serializing_if = "Map::is_empty")]
203 pub request_bodies: Map<String, MaybeRef<RequestBody>>,
204 #[serde(default, skip_serializing_if = "Map::is_empty")]
205 pub headers: Map<String, MaybeRef<Header>>,
206 #[serde(default, skip_serializing_if = "Map::is_empty")]
207 pub security_schemes: Map<String, MaybeRef<SecurityScheme>>,
208 #[serde(default, skip_serializing_if = "Map::is_empty")]
209 pub links: Map<String, MaybeRef<Link>>,
210 #[serde(default, skip_serializing_if = "Map::is_empty")]
211 pub callbacks: Map<String, MaybeRef<Callback>>,
212 #[serde(default, skip_serializing_if = "Map::is_empty")]
213 pub path_items: Map<String, PathItem>,
214
215 #[serde(flatten)]
216 pub extensions: Extensions,
217 }
218}
219
220impl Components {
221 pub fn resolve_schema<'a>(&'a self, mut schema: &'a MaybeRef<Schema>) -> Option<&'a Schema> {
222 loop {
223 match schema {
224 MaybeRef::T(schema) => break Some(schema),
225 MaybeRef::Ref(r) => {
226 let name = r.get_components_schema_name()?;
227 schema = self.schemas.get(name)?;
228 }
229 }
230 }
231 }
232}
233
234macros::define_openapi_spec_object! {
235 #[derive(Default)]
236 pub struct Paths {
237 #[serde(flatten)]
238 pub paths: Map<String, PathItem>,
239
240 #[serde(flatten)]
241 pub extensions: Extensions,
242 }
243}
244
245macros::define_openapi_spec_object! {
246 #[derive(Default)]
247 pub struct PathItem {
248 #[serde(rename = "$ref")]
249 pub r#ref: Option<String>,
250 pub summary: Option<String>,
251 pub description: Option<String>,
252 pub get: Option<Operation>,
253 pub put: Option<Operation>,
254 pub post: Option<Operation>,
255 pub delete: Option<Operation>,
256 pub options: Option<Operation>,
257 pub head: Option<Operation>,
258 pub patch: Option<Operation>,
259 pub trace: Option<Operation>,
260 #[serde(default, skip_serializing_if = "Vec::is_empty")]
261 pub servers: Vec<Server>,
262 #[serde(default, skip_serializing_if = "Vec::is_empty")]
263 pub parameters: Vec<MaybeRef<Parameter>>,
264
265 #[serde(flatten)]
266 pub extensions: Extensions,
267 }
268}
269
270impl PathItem {
271 pub fn operation_by_method_mut(&mut self, method: Method) -> Option<&mut Option<Operation>> {
272 Some(match method {
273 Method::GET => &mut self.get,
274 Method::PUT => &mut self.put,
275 Method::POST => &mut self.post,
276 Method::DELETE => &mut self.delete,
277 Method::OPTIONS => &mut self.options,
278 Method::HEAD => &mut self.head,
279 Method::PATCH => &mut self.patch,
280 Method::TRACE => &mut self.trace,
281 _ => return None,
282 })
283 }
284 pub fn operations_mut(&mut self) -> impl Iterator<Item = &mut Operation> {
285 [
286 &mut self.delete,
287 &mut self.get,
288 &mut self.head,
289 &mut self.options,
290 &mut self.patch,
291 &mut self.post,
292 &mut self.put,
293 &mut self.trace,
294 ]
295 .into_iter()
296 .filter_map(|op| op.as_mut())
297 }
298}
299
300macros::define_openapi_spec_object! {
301 #[derive(Default)]
302 pub struct Operation {
303 #[serde(default, skip_serializing_if = "Vec::is_empty")]
304 pub tags: Vec<String>,
305 pub summary: Option<String>,
306 pub description: Option<String>,
307 pub external_docs: Option<ExternalDocs>,
308 pub operation_id: Option<String>,
309 #[serde(default, skip_serializing_if = "Vec::is_empty")]
310 pub parameters: Vec<MaybeRef<Parameter>>,
311 pub request_body: Option<MaybeRef<RequestBody>>,
312 #[serde(default, skip_serializing_if = "Responses::is_empty")]
313 pub responses: Responses,
314 #[serde(default, skip_serializing_if = "Map::is_empty")]
315 pub callbacks: Map<String, MaybeRef<Callback>>,
316 pub deprecated: Option<bool>,
317 pub security: Option<Vec<SecurityRequirement>>,
318 #[serde(default, skip_serializing_if = "Vec::is_empty")]
319 pub servers: Vec<Server>,
320
321 #[serde(flatten)]
322 pub extensions: Extensions,
323 }
324}
325
326impl Operation {
327 pub fn add_response(&mut self, status_code: String, response: MaybeRef<Response>) {
328 match self.responses.responses.entry(status_code) {
329 Entry::Occupied(entry) => {
330 panic!("colliding responses for status code {}", entry.key());
331 }
332 Entry::Vacant(entry) => {
333 entry.insert(response);
334 }
335 }
336 }
337}
338
339macros::define_openapi_spec_object! {
340 pub struct ExternalDocs {
341 pub description: Option<String>,
342 pub url: String,
343
344 #[serde(flatten)]
345 pub extensions: Extensions,
346 }
347}
348
349impl ExternalDocs {
350 pub fn new(url: String) -> Self {
351 Self {
352 url,
353 description: Default::default(),
354 extensions: Default::default(),
355 }
356 }
357}
358
359macros::define_openapi_spec_object! {
360 pub struct Parameter {
361 pub name: String,
362 pub r#in: ParameterIn,
363 pub description: Option<String>,
364 pub required: Option<bool>,
365 pub deprecated: Option<bool>,
366 pub allow_empty_value: Option<bool>,
367 pub style: Option<String>,
368 pub explode: Option<bool>,
369 pub allow_reserved: Option<bool>,
370 pub schema: Option<MaybeRef<Schema>>,
371 pub example: Option<Value>,
372 #[serde(default, skip_serializing_if = "Map::is_empty")]
373 pub examples: Map<String, MaybeRef<Example>>,
374 #[serde(default, skip_serializing_if = "Map::is_empty")]
375 pub content: Map<String, MediaTypeContent>,
376
377 #[serde(flatten)]
378 pub extensions: Extensions,
379 }
380}
381
382#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
383#[serde(rename_all = "camelCase")]
384#[non_exhaustive]
385pub enum ParameterIn {
386 Query,
387 Header,
388 Path,
389 Cookie,
390}
391
392impl Parameter {
393 pub fn new(name: String, r#in: ParameterIn) -> Self {
394 Self {
395 name,
396 r#in,
397 description: Default::default(),
398 required: Default::default(),
399 deprecated: Default::default(),
400 allow_empty_value: Default::default(),
401 style: Default::default(),
402 explode: Default::default(),
403 allow_reserved: Default::default(),
404 schema: Default::default(),
405 example: Default::default(),
406 examples: Default::default(),
407 content: Default::default(),
408 extensions: Default::default(),
409 }
410 }
411}
412
413macros::define_openapi_spec_object! {
414 #[derive(Default)]
415 pub struct RequestBody {
416 pub description: Option<String>,
417 pub content: Map<String, MediaTypeContent>,
418 pub required: Option<bool>,
419
420 #[serde(flatten)]
421 pub extensions: Extensions,
422 }
423}
424
425impl RequestBody {
426 pub fn new(content: Map<String, MediaTypeContent>) -> Self {
427 Self {
428 content,
429 description: Default::default(),
430 required: Default::default(),
431 extensions: Default::default(),
432 }
433 }
434}
435
436macros::define_openapi_spec_object! {
437 #[derive(Default)]
438 pub struct MediaTypeContent {
439 pub schema: Option<MaybeRef<Schema>>,
440 pub example: Option<Value>,
441 #[serde(default, skip_serializing_if = "Map::is_empty")]
442 pub examples: Map<String, MaybeRef<Example>>,
443 #[serde(default, skip_serializing_if = "Map::is_empty")]
444 pub encoding: Map<String, Encoding>,
445
446 #[serde(flatten)]
447 pub extensions: Extensions,
448 }
449}
450
451macros::define_openapi_spec_object! {
452 #[derive(Default)]
453 pub struct Encoding {
454 pub content_type: Option<String>,
455 #[serde(default, skip_serializing_if = "Map::is_empty")]
456 pub headers: Map<String, MaybeRef<Header>>,
457
458 #[serde(flatten)]
459 pub extensions: Extensions,
460 }
461}
462
463macros::define_openapi_spec_object! {
464 #[derive(Default)]
465 pub struct Responses {
466 #[serde(flatten, default, skip_serializing_if = "Map::is_empty")]
467 pub responses: Map<String, MaybeRef<Response>>,
468
469 #[serde(flatten)]
470 pub extensions: Extensions,
471 }
472}
473
474impl Responses {
475 pub fn is_empty(&self) -> bool {
476 self.responses.is_empty() && self.extensions.is_empty()
477 }
478 pub fn merge_with(&mut self, other: Responses) {
479 for (status_code, response) in other.responses {
480 match self.responses.entry(status_code) {
481 Entry::Occupied(mut entry) => merge_response_into(entry.get_mut(), response),
482 Entry::Vacant(entry) => {
483 entry.insert(response);
484 }
485 }
486 }
487 self.extensions.merge_with(other.extensions);
488 }
489 pub fn merge_iter(iter: impl IntoIterator<Item = Self>) -> Option<Self> {
490 let mut iter = iter.into_iter();
491 let mut responses = iter.next()?;
492 for next in iter {
493 responses.merge_with(next);
494 }
495 Some(responses)
496 }
497}
498
499pub fn merge_response_into(_a: &mut MaybeRef<Response>, _b: MaybeRef<Response>) {
504 panic!("cannot merge responses");
505}
506
507pub fn merge_responses_iter(
512 iter: impl IntoIterator<Item = MaybeRef<Response>>,
513) -> Option<MaybeRef<Response>> {
514 let mut iter = iter.into_iter();
515 let mut response = iter.next()?;
516 for next in iter {
517 merge_response_into(&mut response, next);
518 }
519 Some(response)
520}
521
522macros::define_openapi_spec_object! {
523 #[derive(Default)]
524 pub struct Response {
525 pub description: String,
526 #[serde(default, skip_serializing_if = "Map::is_empty")]
527 pub headers: Map<String, MaybeRef<Header>>,
528 #[serde(default, skip_serializing_if = "Map::is_empty")]
529 pub content: Map<String, MediaTypeContent>,
530 #[serde(default, skip_serializing_if = "Map::is_empty")]
531 pub links: Map<String, MaybeRef<Link>>,
532
533 #[serde(flatten)]
534 pub extensions: Extensions,
535 }
536}
537
538macros::define_openapi_spec_object! {
539 #[derive(Default)]
540 pub struct Callback {
541 #[serde(flatten)]
542 pub callbacks: Map<String, PathItem>,
543
544 #[serde(flatten)]
545 pub extensions: Extensions,
546 }
547}
548
549macros::define_openapi_spec_object! {
550 #[derive(Default)]
551 pub struct Example {
552 pub summary: Option<String>,
553 pub description: Option<String>,
554 pub value: Option<Value>,
555 pub external_value: Option<String>,
556
557 #[serde(flatten)]
558 pub extensions: Extensions,
559 }
560}
561
562macros::define_openapi_spec_object! {
563 #[derive(Default)]
564 pub struct Link {
565 pub operation_ref: Option<String>,
566 pub operation_id: Option<String>,
567 #[serde(default, skip_serializing_if = "Map::is_empty")]
568 pub parameters: Map<String, Value>,
569 pub request_body: Option<Value>,
570 pub description: Option<String>,
571 pub server: Option<Server>,
572
573 #[serde(flatten)]
574 pub extensions: Extensions,
575 }
576}
577
578macros::define_openapi_spec_object! {
579 #[derive(Default)]
580 pub struct Header {
581 pub description: Option<String>,
582 pub required: Option<bool>,
583 pub deprecated: Option<bool>,
584 pub style: Option<String>,
585 pub explode: Option<bool>,
586 pub schema: Option<MaybeRef<Schema>>,
587 pub example: Option<Value>,
588 #[serde(default, skip_serializing_if = "Map::is_empty")]
589 pub examples: Map<String, MaybeRef<Example>>,
590 #[serde(default, skip_serializing_if = "Map::is_empty")]
591 pub content: Map<String, MediaTypeContent>,
592
593 #[serde(flatten)]
594 pub extensions: Extensions,
595 }
596}
597
598macros::define_openapi_spec_object! {
599 pub struct Tag {
600 pub name: String,
601 pub description: Option<String>,
602 pub external_docs: Option<ExternalDocs>,
603
604 #[serde(flatten)]
605 pub extensions: Extensions,
606 }
607}
608
609impl Tag {
610 pub fn new(name: impl Into<String>) -> Self {
611 Self {
612 name: name.into(),
613 description: Default::default(),
614 external_docs: Default::default(),
615 extensions: Default::default(),
616 }
617 }
618}
619
620macros::define_openapi_spec_object! {
621 pub struct SecurityScheme {
622 #[serde(flatten)]
623 pub r#type: SecuritySchemeType,
624 pub description: Option<String>,
625
626 #[serde(flatten)]
627 pub extensions: Extensions,
628 }
629}
630
631impl SecurityScheme {
632 pub fn new(r#type: SecuritySchemeType) -> Self {
633 Self {
634 r#type,
635 description: Default::default(),
636 extensions: Default::default(),
637 }
638 }
639}
640
641#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
642#[serde(rename_all = "camelCase", tag = "type")]
643#[non_exhaustive]
644#[expect(clippy::large_enum_variant)]
645pub enum SecuritySchemeType {
646 ApiKey(ApiKeySecurityScheme),
647 Http(HttpSecurityScheme),
648 MutualTLS,
649 Oauth2(Oauth2SecurityScheme),
650 OpenIdConnect(OpenIdConnectSecurityScheme),
651}
652
653#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
654#[serde(rename_all = "camelCase", tag = "in", content = "name")]
655#[non_exhaustive]
656pub enum ApiKeySecurityScheme {
657 Query(String),
658 Header(String),
659 Cookie(String),
660}
661
662macros::define_openapi_spec_object! {
663 pub struct HttpSecurityScheme {
664 pub scheme: String,
665 pub bearer_format: Option<String>,
666 }
667}
668
669impl HttpSecurityScheme {
670 pub fn new(scheme: String) -> Self {
671 Self {
672 scheme,
673 bearer_format: None,
674 }
675 }
676}
677
678macros::define_openapi_spec_object! {
679 #[derive(Default)]
680 pub struct Oauth2SecurityScheme {
681 pub flows: OAuthFlows,
682 }
683}
684
685macros::define_openapi_spec_object! {
686 pub struct OpenIdConnectSecurityScheme {
687 pub open_id_connect_url: String,
688 }
689}
690
691impl OpenIdConnectSecurityScheme {
692 pub fn new(open_id_connect_url: String) -> Self {
693 Self {
694 open_id_connect_url,
695 }
696 }
697}
698
699macros::define_openapi_spec_object! {
700 #[derive(Default)]
701 pub struct OAuthFlows {
702 pub implicit: Option<OAuthFlow>,
703 pub password: Option<OAuthFlow>,
704 pub client_credentials: Option<OAuthFlow>,
705 pub authorization_code: Option<OAuthFlow>,
706
707 #[serde(flatten)]
708 pub extensions: Extensions,
709 }
710}
711
712macros::define_openapi_spec_object! {
713 #[derive(Default)]
714 pub struct OAuthFlow {
715 pub authorization_url: Option<String>,
716 pub token_url: Option<String>,
717 pub refresh_url: Option<String>,
718 #[serde(default, skip_serializing_if = "Map::is_empty")]
719 pub scopes: Map<String, String>,
720
721 #[serde(flatten)]
722 pub extensions: Extensions,
723 }
724}
725
726macros::define_openapi_spec_object! {
727 #[derive(Default)]
728 pub struct SecurityRequirement {
729 #[serde(flatten)]
730 pub schemes: Map<String, Vec<String>>,
731 }
732}
733
734impl SecurityRequirement {
735 pub fn is_empty(&self) -> bool {
736 self.schemes.is_empty()
737 }
738}
739
740#[derive(Default, Clone, Debug, PartialEq, Eq)]
741pub struct Extensions(pub Map<String, Value>);
742
743impl Extensions {
744 pub fn merge_with(&mut self, other: Extensions) {
745 merge_maps(&mut self.0, other.0, |value_mut, value| {
746 if *value_mut != value {
747 panic!("colliding extension values")
748 }
749 });
750 }
751}
752
753impl Deref for Extensions {
754 type Target = Map<String, Value>;
755
756 fn deref(&self) -> &Self::Target {
757 &self.0
758 }
759}
760
761impl DerefMut for Extensions {
762 fn deref_mut(&mut self) -> &mut Self::Target {
763 &mut self.0
764 }
765}
766
767impl Serialize for Extensions {
768 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
769 where
770 S: serde::Serializer,
771 {
772 let mut map = serializer.serialize_map(Some(self.0.len()))?;
773 for (k, v) in &self.0 {
774 map.serialize_entry(&format!("x-{k}"), v)?;
775 }
776 map.end()
777 }
778}
779
780impl<'de> Deserialize<'de> for Extensions {
781 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
782 where
783 D: serde::Deserializer<'de>,
784 {
785 let map = Map::<String, Value>::deserialize(deserializer)?;
786 let map = map
787 .into_iter()
788 .filter(|(k, _)| k.starts_with("x-"))
789 .map(|(mut k, v)| {
790 k.replace_range(0..2, "");
791 (k, v)
792 })
793 .collect();
794 Ok(Self(map))
795 }
796}
797
798#[cfg(test)]
799mod tests {
800 use insta::{assert_debug_snapshot, assert_json_snapshot};
801 use serde_json::json;
802
803 use super::*;
804
805 #[test]
806 pub fn extensions() {
807 assert_json_snapshot!(Extensions(Map::from_iter([
808 (String::from("foo"), json!("value")),
809 (String::from("bar"), json!(42))
810 ])));
811 assert_debug_snapshot!(serde_json::from_value::<Extensions>(json!({
812 "x-foo": 42,
813 "bar": "nowhere",
814 "x-foobar": "ok",
815 })));
816 }
817
818 #[test]
819 pub fn defaults() {
820 assert_json_snapshot!(OpenApi::new(
821 "3.0.0".to_owned(),
822 Info::new("Title".to_owned())
823 ));
824 assert_json_snapshot!(Contact::default());
825 assert_json_snapshot!(License::new("GPL".to_owned()));
826 assert_json_snapshot!(Server::new("/url".to_owned()));
827 assert_json_snapshot!(Components::default());
828 assert_json_snapshot!(Paths::default());
829 assert_json_snapshot!(PathItem::default());
830 assert_json_snapshot!(Operation::default());
831 assert_json_snapshot!(ExternalDocs::new("/url".to_owned()));
832 assert_json_snapshot!(Parameter::new("name".to_owned(), ParameterIn::Cookie));
833 assert_json_snapshot!(RequestBody::new(Map::default()));
834 assert_json_snapshot!(MediaTypeContent::default());
835 assert_json_snapshot!(Encoding::default());
836 assert_json_snapshot!(Responses::default());
837 assert_json_snapshot!(Response::default());
838 assert_json_snapshot!(Callback::default());
839 assert_json_snapshot!(Example::default());
840 assert_json_snapshot!(Link::default());
841 assert_json_snapshot!(Header::default());
842 assert_json_snapshot!(Tag::new("name".to_owned()));
843 assert_json_snapshot!(Ref::new("ref".to_owned()));
844 assert_json_snapshot!(SecurityScheme::new(SecuritySchemeType::MutualTLS));
845 assert_json_snapshot!(SecurityScheme::new(SecuritySchemeType::ApiKey(
846 ApiKeySecurityScheme::Cookie("cookie_name".to_owned())
847 )));
848 assert_json_snapshot!(SecurityScheme::new(SecuritySchemeType::Oauth2(
849 Oauth2SecurityScheme::default()
850 )));
851 assert_json_snapshot!(SecurityScheme::new(SecuritySchemeType::Oauth2(
852 Oauth2SecurityScheme::default()
853 .with_flows(OAuthFlows::default().with_implicit(OAuthFlow::default()))
854 )));
855 assert_json_snapshot!(SecurityScheme::new(SecuritySchemeType::OpenIdConnect(
856 OpenIdConnectSecurityScheme::new("/url".to_owned())
857 )));
858 assert_json_snapshot!(SecurityScheme::new(SecuritySchemeType::Http(
859 HttpSecurityScheme::new("scheme".to_owned())
860 )));
861 assert_json_snapshot!(OAuthFlows::default());
862 assert_json_snapshot!(OAuthFlow::default());
863 assert_json_snapshot!(SecurityRequirement::default());
864 }
865}