utoipa/openapi/
content.rs

1//! Implements content object for request body and response.
2use std::collections::BTreeMap;
3
4use serde::{Deserialize, Serialize};
5
6use serde_json::Value;
7
8use super::builder;
9use super::example::Example;
10use super::{encoding::Encoding, set_value, RefOr, Schema};
11
12builder! {
13    ContentBuilder;
14
15
16    /// Content holds request body content or response content.
17    #[derive(Serialize, Deserialize, Default, Clone, PartialEq)]
18    #[cfg_attr(feature = "debug", derive(Debug))]
19    #[non_exhaustive]
20    pub struct Content {
21        /// Schema used in response body or request body.
22        pub schema: RefOr<Schema>,
23
24        /// Example for request body or response body.
25        #[serde(skip_serializing_if = "Option::is_none")]
26        pub example: Option<Value>,
27
28        /// Examples of the request body or response body. [`Content::examples`] should match to
29        /// media type and specified schema if present. [`Content::examples`] and
30        /// [`Content::example`] are mutually exclusive. If both are defined `examples` will
31        /// override value in `example`.
32        #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
33        pub examples: BTreeMap<String, RefOr<Example>>,
34
35        /// A map between a property name and its encoding information.
36        ///
37        /// The key, being the property name, MUST exist in the [`Content::schema`] as a property, with
38        /// `schema` being a [`Schema::Object`] and this object containing the same property key in
39        /// [`Object::properties`](crate::openapi::schema::Object::properties).
40        ///
41        /// The encoding object SHALL only apply to `request_body` objects when the media type is
42        /// multipart or `application/x-www-form-urlencoded`.
43        #[serde(skip_serializing_if = "BTreeMap::is_empty", default)]
44        pub encoding: BTreeMap<String, Encoding>,
45    }
46}
47
48impl Content {
49    pub fn new<I: Into<RefOr<Schema>>>(schema: I) -> Self {
50        Self {
51            schema: schema.into(),
52            ..Self::default()
53        }
54    }
55}
56
57impl ContentBuilder {
58    /// Add schema.
59    pub fn schema<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
60        set_value!(self schema component.into())
61    }
62
63    /// Add example of schema.
64    pub fn example(mut self, example: Option<Value>) -> Self {
65        set_value!(self example example)
66    }
67
68    /// Add iterator of _`(N, V)`_ where `N` is name of example and `V` is [`Example`][example] to
69    /// [`Content`] of a request body or response body.
70    ///
71    /// [`Content::examples`] and [`Content::example`] are mutually exclusive. If both are defined
72    /// `examples` will override value in `example`.
73    ///
74    /// [example]: ../example/Example.html
75    pub fn examples_from_iter<
76        E: IntoIterator<Item = (N, V)>,
77        N: Into<String>,
78        V: Into<RefOr<Example>>,
79    >(
80        mut self,
81        examples: E,
82    ) -> Self {
83        self.examples.extend(
84            examples
85                .into_iter()
86                .map(|(name, example)| (name.into(), example.into())),
87        );
88
89        self
90    }
91
92    /// Add an encoding.
93    ///
94    /// The `property_name` MUST exist in the [`Content::schema`] as a property,
95    /// with `schema` being a [`Schema::Object`] and this object containing the same property
96    /// key in [`Object::properties`](crate::openapi::schema::Object::properties).
97    ///
98    /// The encoding object SHALL only apply to `request_body` objects when the media type is
99    /// multipart or `application/x-www-form-urlencoded`.
100    pub fn encoding<S: Into<String>, E: Into<Encoding>>(
101        mut self,
102        property_name: S,
103        encoding: E,
104    ) -> Self {
105        self.encoding.insert(property_name.into(), encoding.into());
106        self
107    }
108}