Skip to main content

openapi_nexus/spec/oas32/spec/
parameter.rs

1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5use super::{
6    ErrorRef, Example, FromRef, MediaType, ObjectOrReference, ObjectSchema, OpenApiV32Spec, Ref,
7    RefType, spec_extensions,
8};
9
10/// Parameter location.
11#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
12#[serde(rename_all = "camelCase")]
13pub enum ParameterIn {
14    Path,
15    Query,
16    Header,
17    Cookie,
18    Querystring,
19}
20
21/// Parameter style.
22#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
23#[serde(rename_all = "camelCase")]
24pub enum ParameterStyle {
25    Matrix,
26    Label,
27    Form,
28    Simple,
29    SpaceDelimited,
30    PipeDelimited,
31    DeepObject,
32}
33
34/// Describes a single operation parameter.
35#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
36#[serde(rename_all = "camelCase")]
37pub struct Parameter {
38    pub name: String,
39
40    #[serde(rename = "in")]
41    pub location: ParameterIn,
42
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub description: Option<String>,
45
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub required: Option<bool>,
48
49    #[serde(default, skip_serializing_if = "Option::is_none")]
50    pub deprecated: Option<bool>,
51
52    #[serde(default, skip_serializing_if = "Option::is_none")]
53    pub allow_empty_value: Option<bool>,
54
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub style: Option<ParameterStyle>,
57
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub explode: Option<bool>,
60
61    #[serde(default, skip_serializing_if = "Option::is_none")]
62    pub allow_reserved: Option<bool>,
63
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub schema: Option<ObjectOrReference<ObjectSchema>>,
66
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub example: Option<serde_json::Value>,
69
70    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
71    pub examples: BTreeMap<String, ObjectOrReference<Example>>,
72
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub content: Option<BTreeMap<String, MediaType>>,
75
76    #[serde(flatten, with = "spec_extensions")]
77    pub extensions: BTreeMap<String, serde_json::Value>,
78}
79
80impl FromRef for Parameter {
81    fn from_ref(spec: &OpenApiV32Spec, path: &str) -> Result<Self, ErrorRef> {
82        let refpath = path.parse::<Ref>()?;
83
84        match refpath.kind {
85            RefType::Parameter => spec
86                .components
87                .as_ref()
88                .and_then(|cs| cs.parameters.get(&refpath.name))
89                .ok_or_else(|| ErrorRef::Unresolvable {
90                    path: path.to_owned(),
91                })
92                .and_then(|oor| oor.resolve(spec)),
93
94            typ => Err(ErrorRef::MismatchedType {
95                expected: typ,
96                actual: RefType::Parameter,
97            }),
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::Parameter;
105
106    #[test]
107    fn deserialization() {
108        let spec = r#"{
109            "name": "foo",
110            "in": "query",
111            "description": "bar",
112            "required": false,
113            "schema": {
114                "type": "string"
115            }
116        }"#;
117
118        let parameter = serde_json::from_str::<Parameter>(spec).unwrap();
119        assert_eq!(parameter.name, "foo");
120    }
121}