openapiv3/operation.rs
1use crate::*;
2use indexmap::IndexMap;
3use serde::{Deserialize, Serialize};
4
5/// Describes a single API operation on a path.
6#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
7#[serde(rename_all = "camelCase")]
8pub struct Operation {
9 /// A list of tags for API documentation control.
10 /// Tags can be used for logical grouping of operations
11 /// by resources or any other qualifier.
12 #[serde(default)]
13 #[serde(skip_serializing_if = "Vec::is_empty")]
14 pub tags: Vec<String>,
15 /// A short summary of what the operation does.
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub summary: Option<String>,
18 /// A verbose explanation of the operation behavior.
19 /// CommonMark syntax MAY be used for rich text representation.
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub description: Option<String>,
22 /// Additional external documentation for this operation.
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub external_docs: Option<ExternalDocumentation>,
25 /// Unique string used to identify the operation.
26 /// The id MUST be unique among all operations described in the API.
27 /// Tools and libraries MAY use the operationId to uniquely identify
28 /// an operation, therefore, it is RECOMMENDED to follow common
29 /// programming naming conventions.
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub operation_id: Option<String>,
32 /// A list of parameters that are applicable for this operation.
33 /// If a parameter is already defined at the Path Item, the new
34 /// definition will override it but can never remove it.
35 /// The list MUST NOT include duplicated parameters. A unique
36 /// parameter is defined by a combination of a name and location.
37 /// The list can use the Reference Object to link to parameters
38 /// that are defined at the OpenAPI Object's components/parameters.
39 #[serde(default)]
40 #[serde(skip_serializing_if = "Vec::is_empty")]
41 pub parameters: Vec<ReferenceOr<Parameter>>,
42 /// The request body applicable for this operation.
43 /// The requestBody is only supported in HTTP methods
44 /// where the HTTP 1.1 specification RFC7231 has explicitly
45 /// defined semantics for request bodies. In other cases where
46 /// the HTTP spec is vague, requestBody SHALL be ignored by consumers.
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub request_body: Option<ReferenceOr<RequestBody>>,
49 /// REQUIRED. The list of possible responses as they are returned
50 /// from executing this operation.
51 pub responses: Responses,
52 /// Declares this operation to be deprecated.Default value is false.
53 #[serde(default, skip_serializing_if = "is_false")]
54 pub deprecated: bool,
55 /// A declaration of which security mechanisms can be used for this operation.
56 /// The list of values includes alternative security requirement objects that can
57 /// be used. Only one of the security requirement objects need to be satisfied to
58 /// authorize a request. This definition overrides any declared top-level security.
59 /// To remove a top-level security declaration, an empty array can be used.
60 #[serde(default)]
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub security: Option<Vec<SecurityRequirement>>,
63 /// An alternative server array to service this operation.
64 /// If an alternative server object is specified at the
65 /// Path Item Object or Root level, it will be overridden by this value.
66 #[serde(default)]
67 #[serde(skip_serializing_if = "Vec::is_empty")]
68 pub servers: Vec<Server>,
69 /// Inline extensions to this object.
70 #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
71 pub extensions: IndexMap<String, serde_json::Value>,
72}
73
74#[cfg(test)]
75mod tests {
76 use crate::{Operation, ReferenceOr, Responses, StatusCode};
77 use indexmap::IndexMap;
78 use serde_yaml::from_str;
79
80 #[test]
81 fn deserialize_responses() {
82 assert_eq!(
83 Operation {
84 responses: Responses {
85 default: None,
86 responses: {
87 let mut map = IndexMap::new();
88 map.insert(StatusCode::Code(200), ReferenceOr::ref_("test"));
89 map
90 },
91 ..Default::default()
92 },
93 ..Default::default()
94 },
95 from_str("{ responses: { 200: { $ref: 'test' } } }").unwrap(),
96 );
97
98 assert_eq!(
99 Operation {
100 responses: Responses {
101 default: None,
102 responses: {
103 let mut map = IndexMap::new();
104 map.insert(StatusCode::Code(666), ReferenceOr::ref_("demo"));
105 map
106 },
107 ..Default::default()
108 },
109 ..Default::default()
110 },
111 from_str("{ responses: { \"666\": { $ref: 'demo' } } }").unwrap(),
112 );
113
114 assert_eq!(
115 Operation {
116 responses: Responses {
117 default: Some(ReferenceOr::ref_("def")),
118 responses: {
119 let mut map = IndexMap::new();
120 map.insert(StatusCode::Code(666), ReferenceOr::ref_("demo"));
121 map.insert(StatusCode::Code(418), ReferenceOr::ref_("demo"));
122 map
123 },
124 ..Default::default()
125 },
126 ..Default::default()
127 },
128 from_str("{ responses: { default: { $ref: 'def' }, \"666\": { $ref: 'demo' }, 418: { $ref: 'demo' } } }").unwrap(),
129 );
130 }
131}