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