salvo_oapi/openapi/
content.rs1use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5use super::encoding::Encoding;
6use super::example::Example;
7use super::{PropMap, RefOr, Schema};
8
9#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq)]
11#[non_exhaustive]
12pub struct Content {
13 #[serde(skip_serializing_if = "Option::is_none")]
15 pub schema: Option<RefOr<Schema>>,
16
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub example: Option<Value>,
20
21 #[serde(skip_serializing_if = "PropMap::is_empty")]
26 pub examples: PropMap<String, RefOr<Example>>,
27
28 #[serde(skip_serializing_if = "PropMap::is_empty", default)]
37 pub encoding: PropMap<String, Encoding>,
38
39 #[serde(skip_serializing_if = "PropMap::is_empty", flatten)]
41 pub extensions: PropMap<String, serde_json::Value>,
42}
43
44impl Content {
45 #[must_use]
47 pub fn new<I: Into<RefOr<Schema>>>(schema: I) -> Self {
48 Self {
49 schema: Some(schema.into()),
50 ..Self::default()
51 }
52 }
53
54 #[must_use]
56 pub fn schema<I: Into<RefOr<Schema>>>(mut self, component: I) -> Self {
57 self.schema = Some(component.into());
58 self
59 }
60
61 #[must_use]
63 pub fn example(mut self, example: Value) -> Self {
64 self.example = Some(example);
65 self
66 }
67
68 #[must_use]
76 pub fn extend_examples<
77 E: IntoIterator<Item = (N, V)>,
78 N: Into<String>,
79 V: Into<RefOr<Example>>,
80 >(
81 mut self,
82 examples: E,
83 ) -> Self {
84 self.examples.extend(
85 examples
86 .into_iter()
87 .map(|(name, example)| (name.into(), example.into())),
88 );
89
90 self
91 }
92
93 #[must_use]
95 pub fn extensions(mut self, extensions: PropMap<String, serde_json::Value>) -> Self {
96 self.extensions = extensions;
97 self
98 }
99
100 #[must_use]
109 pub fn encoding<S: Into<String>, E: Into<Encoding>>(
110 mut self,
111 property_name: S,
112 encoding: E,
113 ) -> Self {
114 self.encoding.insert(property_name.into(), encoding.into());
115 self
116 }
117}
118
119impl From<RefOr<Schema>> for Content {
120 fn from(schema: RefOr<Schema>) -> Self {
121 Self {
122 schema: Some(schema),
123 ..Self::default()
124 }
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use assert_json_diff::assert_json_eq;
131 use serde_json::{Map, json};
132
133 use super::*;
134
135 #[test]
136 fn test_build_content() {
137 let content = Content::new(RefOr::Ref(crate::Ref::from_schema_name("MySchema")))
138 .example(Value::Object(Map::from_iter([(
139 "schema".into(),
140 Value::String("MySchema".to_owned()),
141 )])))
142 .encoding(
143 "schema".to_owned(),
144 Encoding::default().content_type("text/plain"),
145 );
146 assert_json_eq!(
147 content,
148 json!({
149 "schema": {
150 "$ref": "#/components/schemas/MySchema"
151 },
152 "example": {
153 "schema": "MySchema"
154 },
155 "encoding": {
156 "schema": {
157 "contentType": "text/plain"
158 }
159 }
160 })
161 );
162
163 let content = content
164 .schema(RefOr::Ref(crate::Ref::from_schema_name("NewSchema")))
165 .extend_examples([(
166 "example1".to_owned(),
167 Example::new().value(Value::Object(Map::from_iter([(
168 "schema".into(),
169 Value::String("MySchema".to_owned()),
170 )]))),
171 )]);
172 assert_json_eq!(
173 content,
174 json!({
175 "schema": {
176 "$ref": "#/components/schemas/NewSchema"
177 },
178 "example": {
179 "schema": "MySchema"
180 },
181 "examples": {
182 "example1": {
183 "value": {
184 "schema": "MySchema"
185 }
186 }
187 },
188 "encoding": {
189 "schema": {
190 "contentType": "text/plain"
191 }
192 }
193 })
194 );
195 }
196}