openapiv3_1/
content.rs

1//! Implements content object for request body and response.
2use indexmap::IndexMap;
3use serde_json::Value;
4
5use super::encoding::Encoding;
6use super::example::Example;
7use super::extensions::Extensions;
8use super::{RefOr, Schema};
9
10/// Content holds request body content or response content.
11///
12/// [`Content`] implements OpenAPI spec [Media Type Object][media_type]
13///
14/// [media_type]: <https://spec.openapis.org/oas/latest.html#media-type-object>
15#[derive(serde_derive::Serialize, serde_derive::Deserialize, Default, Clone, PartialEq, bon::Builder)]
16#[cfg_attr(feature = "debug", derive(Debug))]
17#[builder(on(_, into))]
18#[non_exhaustive]
19pub struct Content {
20    /// Schema used in response body or request body.
21    #[serde(skip_serializing_if = "Option::is_none", default)]
22    pub schema: Option<Schema>,
23
24    /// Example for request body or response body.
25    #[serde(skip_serializing_if = "Option::is_none", default)]
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 = "IndexMap::is_empty", default)]
33    #[builder(default)]
34    pub examples: IndexMap<String, RefOr<Example>>,
35
36    /// A map between a property name and its encoding information.
37    ///
38    /// The key, being the property name, MUST exist in the [`Content::schema`] as a property, with
39    /// `schema` being a [`Schema::Object`] and this object containing the same property key in
40    /// [`Object::properties`](crate::schema::Object::properties).
41    ///
42    /// The encoding object SHALL only apply to `request_body` objects when the media type is
43    /// multipart or `application/x-www-form-urlencoded`.
44    #[serde(skip_serializing_if = "IndexMap::is_empty", default)]
45    #[builder(default)]
46    pub encoding: IndexMap<String, Encoding>,
47
48    /// Optional extensions "x-something".
49    #[serde(skip_serializing_if = "Option::is_none", default, flatten)]
50    pub extensions: Option<Extensions>,
51}
52
53impl Content {
54    /// Construct a new [`Content`] object for provided _`schema`_.
55    pub fn new<I: Into<Schema>>(schema: Option<I>) -> Self {
56        Self {
57            schema: schema.map(|schema| schema.into()),
58            ..Self::default()
59        }
60    }
61}
62
63impl<S: content_builder::IsComplete> From<ContentBuilder<S>> for Content {
64    fn from(builder: ContentBuilder<S>) -> Self {
65        builder.build()
66    }
67}