pub struct Schema {Show 27 fields
pub schema_type: Option<SchemaType>,
pub format: Option<String>,
pub description: Option<String>,
pub properties: Option<HashMap<String, Schema>>,
pub required: Option<Vec<String>>,
pub items: Option<Box<Schema>>,
pub min_length: Option<usize>,
pub max_length: Option<usize>,
pub pattern: Option<String>,
pub minimum: Option<f64>,
pub maximum: Option<f64>,
pub multiple_of: Option<f64>,
pub min_items: Option<usize>,
pub max_items: Option<usize>,
pub unique_items: Option<bool>,
pub enum: Option<Vec<Value>>,
pub reference: Option<String>,
pub any_of: Option<Vec<Schema>>,
pub all_of: Option<Vec<Schema>>,
pub one_of: Option<Vec<Schema>>,
pub default: Option<Value>,
pub example: Option<Value>,
pub examples: Option<Vec<Value>>,
pub read_only: Option<bool>,
pub write_only: Option<bool>,
pub deprecated: Option<bool>,
pub extensions: Option<HashMap<String, Value>>,
}Expand description
OpenAPI schema object representing a data type.
Fields§
§schema_type: Option<SchemaType>§format: Option<String>§description: Option<String>§properties: Option<HashMap<String, Schema>>§required: Option<Vec<String>>§items: Option<Box<Schema>>§min_length: Option<usize>§max_length: Option<usize>§pattern: Option<String>§minimum: Option<f64>§maximum: Option<f64>§multiple_of: Option<f64>§min_items: Option<usize>§max_items: Option<usize>§unique_items: Option<bool>§enum: Option<Vec<Value>>§reference: Option<String>§any_of: Option<Vec<Schema>>§all_of: Option<Vec<Schema>>§one_of: Option<Vec<Schema>>§default: Option<Value>§example: Option<Value>§examples: Option<Vec<Value>>§read_only: Option<bool>§write_only: Option<bool>§deprecated: Option<bool>§extensions: Option<HashMap<String, Value>>Implementations§
Source§impl Schema
impl Schema
Sourcepub fn string() -> Self
pub fn string() -> Self
Create a string schema.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40/// Admin user: inherits from User AND adds admin field (composition with allOf)
41#[allow(dead_code)]
42struct AdminUser {
43 // Inherits all User fields + additional fields
44 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }
221}
222
223// === User type for allOf example ===
224
225#[allow(dead_code)]
226struct User {
227 email: String,
228 name: String,
229}
230
231impl ToSchema for User {
232 fn schema_name() -> &'static str {
233 "User"
234 }
235
236 fn schema() -> Schema {
237 Schema::object()
238 .property("email", Schema::string().format("email"))
239 .property("name", Schema::string().min_length(1))
240 .required(&["email", "name"])
241 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }
57}
58
59#[allow(dead_code)]
60struct Address {
61 street: String,
62 zip_code: String,
63 city: String,
64}
65
66impl ToSchema for Address {
67 fn schema_name() -> &'static str {
68 "Address"
69 }
70
71 fn schema() -> Schema {
72 Schema::object()
73 .description("Physical address")
74 .property(
75 "street",
76 Schema::string()
77 .min_length(1)
78 .max_length(100)
79 .description("Street address"),
80 )
81 .property(
82 "zipCode",
83 Schema::string()
84 .min_length(5)
85 .max_length(5)
86 .pattern("^[0-9]{5}$")
87 .description("5-digit ZIP code"),
88 )
89 .property(
90 "city",
91 Schema::string()
92 .min_length(2)
93 .max_length(50)
94 .description("City name"),
95 )
96 .required(&["street", "zipCode", "city"])
97 }
98}
99
100#[allow(dead_code)]
101struct Team {
102 name: String,
103 members: Vec<String>, // Simplified - would be Vec<User> in real app
104}
105
106impl ToSchema for Team {
107 fn schema_name() -> &'static str {
108 "Team"
109 }
110
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn integer() -> Self
pub fn integer() -> Self
Create an integer schema.
Examples found in repository?
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }Sourcepub fn number() -> Self
pub fn number() -> Self
Create a number schema.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40/// Admin user: inherits from User AND adds admin field (composition with allOf)
41#[allow(dead_code)]
42struct AdminUser {
43 // Inherits all User fields + additional fields
44 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }Sourcepub fn boolean() -> Self
pub fn boolean() -> Self
Create a boolean schema.
Examples found in repository?
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }Sourcepub fn array(items: Schema) -> Self
pub fn array(items: Schema) -> Self
Create an array schema.
Examples found in repository?
More examples
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn object() -> Self
pub fn object() -> Self
Create an object schema.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40/// Admin user: inherits from User AND adds admin field (composition with allOf)
41#[allow(dead_code)]
42struct AdminUser {
43 // Inherits all User fields + additional fields
44 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }
221}
222
223// === User type for allOf example ===
224
225#[allow(dead_code)]
226struct User {
227 email: String,
228 name: String,
229}
230
231impl ToSchema for User {
232 fn schema_name() -> &'static str {
233 "User"
234 }
235
236 fn schema() -> Schema {
237 Schema::object()
238 .property("email", Schema::string().format("email"))
239 .property("name", Schema::string().min_length(1))
240 .required(&["email", "name"])
241 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }
57}
58
59#[allow(dead_code)]
60struct Address {
61 street: String,
62 zip_code: String,
63 city: String,
64}
65
66impl ToSchema for Address {
67 fn schema_name() -> &'static str {
68 "Address"
69 }
70
71 fn schema() -> Schema {
72 Schema::object()
73 .description("Physical address")
74 .property(
75 "street",
76 Schema::string()
77 .min_length(1)
78 .max_length(100)
79 .description("Street address"),
80 )
81 .property(
82 "zipCode",
83 Schema::string()
84 .min_length(5)
85 .max_length(5)
86 .pattern("^[0-9]{5}$")
87 .description("5-digit ZIP code"),
88 )
89 .property(
90 "city",
91 Schema::string()
92 .min_length(2)
93 .max_length(50)
94 .description("City name"),
95 )
96 .required(&["street", "zipCode", "city"])
97 }
98}
99
100#[allow(dead_code)]
101struct Team {
102 name: String,
103 members: Vec<String>, // Simplified - would be Vec<User> in real app
104}
105
106impl ToSchema for Team {
107 fn schema_name() -> &'static str {
108 "Team"
109 }
110
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn reference(name: &str) -> Self
pub fn reference(name: &str) -> Self
Create a reference to another schema.
Examples found in repository?
More examples
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn format(self, format: impl Into<String>) -> Self
pub fn format(self, format: impl Into<String>) -> Self
Set the format (e.g., “email”, “date-time”).
Examples found in repository?
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }More examples
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }
221}
222
223// === User type for allOf example ===
224
225#[allow(dead_code)]
226struct User {
227 email: String,
228 name: String,
229}
230
231impl ToSchema for User {
232 fn schema_name() -> &'static str {
233 "User"
234 }
235
236 fn schema() -> Schema {
237 Schema::object()
238 .property("email", Schema::string().format("email"))
239 .property("name", Schema::string().min_length(1))
240 .required(&["email", "name"])
241 }Sourcepub fn description(self, desc: impl Into<String>) -> Self
pub fn description(self, desc: impl Into<String>) -> Self
Set the description.
Examples found in repository?
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }
57}
58
59#[allow(dead_code)]
60struct Address {
61 street: String,
62 zip_code: String,
63 city: String,
64}
65
66impl ToSchema for Address {
67 fn schema_name() -> &'static str {
68 "Address"
69 }
70
71 fn schema() -> Schema {
72 Schema::object()
73 .description("Physical address")
74 .property(
75 "street",
76 Schema::string()
77 .min_length(1)
78 .max_length(100)
79 .description("Street address"),
80 )
81 .property(
82 "zipCode",
83 Schema::string()
84 .min_length(5)
85 .max_length(5)
86 .pattern("^[0-9]{5}$")
87 .description("5-digit ZIP code"),
88 )
89 .property(
90 "city",
91 Schema::string()
92 .min_length(2)
93 .max_length(50)
94 .description("City name"),
95 )
96 .required(&["street", "zipCode", "city"])
97 }
98}
99
100#[allow(dead_code)]
101struct Team {
102 name: String,
103 members: Vec<String>, // Simplified - would be Vec<User> in real app
104}
105
106impl ToSchema for Team {
107 fn schema_name() -> &'static str {
108 "Team"
109 }
110
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn property(self, name: impl Into<String>, schema: Schema) -> Self
pub fn property(self, name: impl Into<String>, schema: Schema) -> Self
Add a property to an object schema.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40/// Admin user: inherits from User AND adds admin field (composition with allOf)
41#[allow(dead_code)]
42struct AdminUser {
43 // Inherits all User fields + additional fields
44 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }
221}
222
223// === User type for allOf example ===
224
225#[allow(dead_code)]
226struct User {
227 email: String,
228 name: String,
229}
230
231impl ToSchema for User {
232 fn schema_name() -> &'static str {
233 "User"
234 }
235
236 fn schema() -> Schema {
237 Schema::object()
238 .property("email", Schema::string().format("email"))
239 .property("name", Schema::string().min_length(1))
240 .required(&["email", "name"])
241 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }
57}
58
59#[allow(dead_code)]
60struct Address {
61 street: String,
62 zip_code: String,
63 city: String,
64}
65
66impl ToSchema for Address {
67 fn schema_name() -> &'static str {
68 "Address"
69 }
70
71 fn schema() -> Schema {
72 Schema::object()
73 .description("Physical address")
74 .property(
75 "street",
76 Schema::string()
77 .min_length(1)
78 .max_length(100)
79 .description("Street address"),
80 )
81 .property(
82 "zipCode",
83 Schema::string()
84 .min_length(5)
85 .max_length(5)
86 .pattern("^[0-9]{5}$")
87 .description("5-digit ZIP code"),
88 )
89 .property(
90 "city",
91 Schema::string()
92 .min_length(2)
93 .max_length(50)
94 .description("City name"),
95 )
96 .required(&["street", "zipCode", "city"])
97 }
98}
99
100#[allow(dead_code)]
101struct Team {
102 name: String,
103 members: Vec<String>, // Simplified - would be Vec<User> in real app
104}
105
106impl ToSchema for Team {
107 fn schema_name() -> &'static str {
108 "Team"
109 }
110
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn required(self, fields: &[&str]) -> Self
pub fn required(self, fields: &[&str]) -> Self
Set required fields.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40/// Admin user: inherits from User AND adds admin field (composition with allOf)
41#[allow(dead_code)]
42struct AdminUser {
43 // Inherits all User fields + additional fields
44 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }
221}
222
223// === User type for allOf example ===
224
225#[allow(dead_code)]
226struct User {
227 email: String,
228 name: String,
229}
230
231impl ToSchema for User {
232 fn schema_name() -> &'static str {
233 "User"
234 }
235
236 fn schema() -> Schema {
237 Schema::object()
238 .property("email", Schema::string().format("email"))
239 .property("name", Schema::string().min_length(1))
240 .required(&["email", "name"])
241 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }
57}
58
59#[allow(dead_code)]
60struct Address {
61 street: String,
62 zip_code: String,
63 city: String,
64}
65
66impl ToSchema for Address {
67 fn schema_name() -> &'static str {
68 "Address"
69 }
70
71 fn schema() -> Schema {
72 Schema::object()
73 .description("Physical address")
74 .property(
75 "street",
76 Schema::string()
77 .min_length(1)
78 .max_length(100)
79 .description("Street address"),
80 )
81 .property(
82 "zipCode",
83 Schema::string()
84 .min_length(5)
85 .max_length(5)
86 .pattern("^[0-9]{5}$")
87 .description("5-digit ZIP code"),
88 )
89 .property(
90 "city",
91 Schema::string()
92 .min_length(2)
93 .max_length(50)
94 .description("City name"),
95 )
96 .required(&["street", "zipCode", "city"])
97 }
98}
99
100#[allow(dead_code)]
101struct Team {
102 name: String,
103 members: Vec<String>, // Simplified - would be Vec<User> in real app
104}
105
106impl ToSchema for Team {
107 fn schema_name() -> &'static str {
108 "Team"
109 }
110
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn min_length(self, min: usize) -> Self
pub fn min_length(self, min: usize) -> Self
Set minimum length for strings.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40/// Admin user: inherits from User AND adds admin field (composition with allOf)
41#[allow(dead_code)]
42struct AdminUser {
43 // Inherits all User fields + additional fields
44 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }
221}
222
223// === User type for allOf example ===
224
225#[allow(dead_code)]
226struct User {
227 email: String,
228 name: String,
229}
230
231impl ToSchema for User {
232 fn schema_name() -> &'static str {
233 "User"
234 }
235
236 fn schema() -> Schema {
237 Schema::object()
238 .property("email", Schema::string().format("email"))
239 .property("name", Schema::string().min_length(1))
240 .required(&["email", "name"])
241 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }
57}
58
59#[allow(dead_code)]
60struct Address {
61 street: String,
62 zip_code: String,
63 city: String,
64}
65
66impl ToSchema for Address {
67 fn schema_name() -> &'static str {
68 "Address"
69 }
70
71 fn schema() -> Schema {
72 Schema::object()
73 .description("Physical address")
74 .property(
75 "street",
76 Schema::string()
77 .min_length(1)
78 .max_length(100)
79 .description("Street address"),
80 )
81 .property(
82 "zipCode",
83 Schema::string()
84 .min_length(5)
85 .max_length(5)
86 .pattern("^[0-9]{5}$")
87 .description("5-digit ZIP code"),
88 )
89 .property(
90 "city",
91 Schema::string()
92 .min_length(2)
93 .max_length(50)
94 .description("City name"),
95 )
96 .required(&["street", "zipCode", "city"])
97 }
98}
99
100#[allow(dead_code)]
101struct Team {
102 name: String,
103 members: Vec<String>, // Simplified - would be Vec<User> in real app
104}
105
106impl ToSchema for Team {
107 fn schema_name() -> &'static str {
108 "Team"
109 }
110
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn max_length(self, max: usize) -> Self
pub fn max_length(self, max: usize) -> Self
Set maximum length for strings.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }
57}
58
59#[allow(dead_code)]
60struct Address {
61 street: String,
62 zip_code: String,
63 city: String,
64}
65
66impl ToSchema for Address {
67 fn schema_name() -> &'static str {
68 "Address"
69 }
70
71 fn schema() -> Schema {
72 Schema::object()
73 .description("Physical address")
74 .property(
75 "street",
76 Schema::string()
77 .min_length(1)
78 .max_length(100)
79 .description("Street address"),
80 )
81 .property(
82 "zipCode",
83 Schema::string()
84 .min_length(5)
85 .max_length(5)
86 .pattern("^[0-9]{5}$")
87 .description("5-digit ZIP code"),
88 )
89 .property(
90 "city",
91 Schema::string()
92 .min_length(2)
93 .max_length(50)
94 .description("City name"),
95 )
96 .required(&["street", "zipCode", "city"])
97 }
98}
99
100#[allow(dead_code)]
101struct Team {
102 name: String,
103 members: Vec<String>, // Simplified - would be Vec<User> in real app
104}
105
106impl ToSchema for Team {
107 fn schema_name() -> &'static str {
108 "Team"
109 }
110
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn pattern(self, pattern: impl Into<String>) -> Self
pub fn pattern(self, pattern: impl Into<String>) -> Self
Set regex pattern for strings.
Examples found in repository?
71 fn schema() -> Schema {
72 Schema::object()
73 .description("Physical address")
74 .property(
75 "street",
76 Schema::string()
77 .min_length(1)
78 .max_length(100)
79 .description("Street address"),
80 )
81 .property(
82 "zipCode",
83 Schema::string()
84 .min_length(5)
85 .max_length(5)
86 .pattern("^[0-9]{5}$")
87 .description("5-digit ZIP code"),
88 )
89 .property(
90 "city",
91 Schema::string()
92 .min_length(2)
93 .max_length(50)
94 .description("City name"),
95 )
96 .required(&["street", "zipCode", "city"])
97 }Sourcepub fn minimum(self, min: impl Into<f64>) -> Self
pub fn minimum(self, min: impl Into<f64>) -> Self
Set minimum value for numbers.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40/// Admin user: inherits from User AND adds admin field (composition with allOf)
41#[allow(dead_code)]
42struct AdminUser {
43 // Inherits all User fields + additional fields
44 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }
104}
105
106// === 3. Request/Response Modifiers: readOnly, writeOnly, deprecated ===
107
108#[allow(dead_code)]
109struct UserAccount {
110 id: String,
111 email: String,
112 password: String,
113 created_at: String,
114 old_username: Option<String>,
115}
116
117impl ToSchema for UserAccount {
118 fn schema_name() -> &'static str {
119 "UserAccount"
120 }
121
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }
158}
159
160// === 4. Vendor Extensions for Non-Mappable Validations ===
161
162#[allow(dead_code)]
163struct DateRange {
164 start_date: String,
165 end_date: String,
166}
167
168impl ToSchema for DateRange {
169 fn schema_name() -> &'static str {
170 "DateRange"
171 }
172
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }Sourcepub fn maximum(self, max: impl Into<f64>) -> Self
pub fn maximum(self, max: impl Into<f64>) -> Self
Set maximum value for numbers.
Examples found in repository?
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }Sourcepub fn multiple_of(self, divisor: impl Into<f64>) -> Self
pub fn multiple_of(self, divisor: impl Into<f64>) -> Self
Set multiple_of constraint for numbers.
Sourcepub fn min_items(self, min: usize) -> Self
pub fn min_items(self, min: usize) -> Self
Set minimum items for arrays.
Examples found in repository?
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn max_items(self, max: usize) -> Self
pub fn max_items(self, max: usize) -> Self
Set maximum items for arrays.
Examples found in repository?
111 fn schema() -> Schema {
112 Schema::object()
113 .description("Team of users")
114 .property(
115 "name",
116 Schema::string()
117 .min_length(1)
118 .max_length(50)
119 .description("Team name"),
120 )
121 .property(
122 "members",
123 Schema::array(Schema::reference("User"))
124 .min_items(1)
125 .max_items(10)
126 .description("Team members (1-10 users)"),
127 )
128 .required(&["name", "members"])
129 }Sourcepub fn unique_items(self, unique: bool) -> Self
pub fn unique_items(self, unique: bool) -> Self
Set unique items constraint for arrays.
Sourcepub fn enum_values<T: Serialize>(self, values: &[T]) -> Self
pub fn enum_values<T: Serialize>(self, values: &[T]) -> Self
Set enum values.
§Panics
Panics if any value cannot be serialized to JSON.
Use Self::try_enum_values for a non-panicking alternative.
Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }
38}
39
40/// Admin user: inherits from User AND adds admin field (composition with allOf)
41#[allow(dead_code)]
42struct AdminUser {
43 // Inherits all User fields + additional fields
44 admin: bool,
45}
46
47impl ToSchema for AdminUser {
48 fn schema_name() -> &'static str {
49 "AdminUser"
50 }
51
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }More examples
26 fn schema() -> Schema {
27 Schema::object()
28 .description("User account")
29 .property(
30 "email",
31 Schema::string()
32 .format("email")
33 .description("User email address"),
34 )
35 .property(
36 "age",
37 Schema::integer()
38 .minimum(18)
39 .maximum(120)
40 .description("User age (18-120)"),
41 )
42 .property(
43 "name",
44 Schema::string()
45 .min_length(3)
46 .max_length(50)
47 .description("User full name"),
48 )
49 .property(
50 "status",
51 Schema::string()
52 .enum_values(&["active", "pending", "inactive"])
53 .description("User account status"),
54 )
55 .required(&["email", "age", "name", "status"])
56 }Sourcepub fn try_enum_values<T: Serialize>(self, values: &[T]) -> Result<Self, Error>
pub fn try_enum_values<T: Serialize>(self, values: &[T]) -> Result<Self, Error>
Set enum values (non-panicking version).
Returns an error if any value cannot be serialized to JSON.
Sourcepub fn any_of(schemas: Vec<Schema>) -> Self
pub fn any_of(schemas: Vec<Schema>) -> Self
Create a schema that matches any of the given schemas (union type).
§Example
use domainstack_schema::Schema;
let schema = Schema::any_of(vec![
Schema::string(),
Schema::integer(),
]);Examples found in repository?
25 fn schema() -> Schema {
26 Schema::any_of(vec![
27 Schema::object()
28 .property("type", Schema::string().enum_values(&["card"]))
29 .property("cardNumber", Schema::string().min_length(16).max_length(16))
30 .property("cvv", Schema::string().min_length(3).max_length(4))
31 .required(&["type", "cardNumber", "cvv"]),
32 Schema::object()
33 .property("type", Schema::string().enum_values(&["cash"]))
34 .property("amount", Schema::number().minimum(0))
35 .required(&["type", "amount"]),
36 ])
37 }Sourcepub fn all_of(schemas: Vec<Schema>) -> Self
pub fn all_of(schemas: Vec<Schema>) -> Self
Create a schema that matches all of the given schemas (intersection/composition).
§Example
use domainstack_schema::Schema;
let schema = Schema::all_of(vec![
Schema::reference("BaseUser"),
Schema::object().property("admin", Schema::boolean()),
]);Sourcepub fn one_of(schemas: Vec<Schema>) -> Self
pub fn one_of(schemas: Vec<Schema>) -> Self
Create a schema that matches exactly one of the given schemas (discriminated union).
§Example
use domainstack_schema::Schema;
let schema = Schema::one_of(vec![
Schema::object().property("type", Schema::string().enum_values(&["card"])),
Schema::object().property("type", Schema::string().enum_values(&["cash"])),
]);Sourcepub fn default<T: Serialize>(self, value: T) -> Self
pub fn default<T: Serialize>(self, value: T) -> Self
Set a default value for this schema.
§Example
use domainstack_schema::Schema;
use serde_json::json;
let schema = Schema::string().default(json!("guest"));§Panics
Panics if the value cannot be serialized to JSON.
Use Self::try_default for a non-panicking alternative.
Examples found in repository?
52 fn schema() -> Schema {
53 Schema::all_of(vec![
54 Schema::reference("User"),
55 Schema::object()
56 .property("admin", Schema::boolean().default(json!(false)))
57 .property("permissions", Schema::array(Schema::string()))
58 .required(&["admin"]),
59 ])
60 .description("Admin user with elevated permissions")
61 }
62}
63
64// === 2. Metadata: default, example, examples ===
65
66#[allow(dead_code)]
67struct UserSettings {
68 theme: String,
69 language: String,
70 notifications_enabled: bool,
71}
72
73impl ToSchema for UserSettings {
74 fn schema_name() -> &'static str {
75 "UserSettings"
76 }
77
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }Sourcepub fn try_default<T: Serialize>(self, value: T) -> Result<Self, Error>
pub fn try_default<T: Serialize>(self, value: T) -> Result<Self, Error>
Set a default value for this schema (non-panicking version).
Returns an error if the value cannot be serialized to JSON.
Sourcepub fn example<T: Serialize>(self, value: T) -> Self
pub fn example<T: Serialize>(self, value: T) -> Self
Set an example value for this schema.
§Example
use domainstack_schema::Schema;
use serde_json::json;
let schema = Schema::string().example(json!("john_doe"));§Panics
Panics if the value cannot be serialized to JSON.
Use Self::try_example for a non-panicking alternative.
Examples found in repository?
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }Sourcepub fn try_example<T: Serialize>(self, value: T) -> Result<Self, Error>
pub fn try_example<T: Serialize>(self, value: T) -> Result<Self, Error>
Set an example value for this schema (non-panicking version).
Returns an error if the value cannot be serialized to JSON.
Sourcepub fn examples<T: Serialize>(self, values: Vec<T>) -> Self
pub fn examples<T: Serialize>(self, values: Vec<T>) -> Self
Set multiple example values for this schema.
§Example
use domainstack_schema::Schema;
use serde_json::json;
let schema = Schema::string().examples(vec![
json!("alice"),
json!("bob"),
]);§Panics
Panics if any value cannot be serialized to JSON.
Use Self::try_examples for a non-panicking alternative.
Examples found in repository?
78 fn schema() -> Schema {
79 Schema::object()
80 .description("User preferences and settings")
81 .property(
82 "theme",
83 Schema::string()
84 .enum_values(&["light", "dark", "auto"])
85 .default(json!("auto"))
86 .example(json!("dark"))
87 .description("UI theme preference"),
88 )
89 .property(
90 "language",
91 Schema::string()
92 .default(json!("en"))
93 .examples(vec![json!("en"), json!("es"), json!("fr")])
94 .description("Preferred language code (ISO 639-1)"),
95 )
96 .property(
97 "notificationsEnabled",
98 Schema::boolean()
99 .default(json!(true))
100 .description("Enable/disable notifications"),
101 )
102 .required(&["theme", "language"])
103 }Sourcepub fn try_examples<T: Serialize>(self, values: Vec<T>) -> Result<Self, Error>
pub fn try_examples<T: Serialize>(self, values: Vec<T>) -> Result<Self, Error>
Set multiple example values for this schema (non-panicking version).
Returns an error if any value cannot be serialized to JSON.
Sourcepub fn read_only(self, read_only: bool) -> Self
pub fn read_only(self, read_only: bool) -> Self
Mark this field as read-only (returned in responses, not accepted in requests).
§Example
use domainstack_schema::Schema;
let schema = Schema::string().read_only(true);Examples found in repository?
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }Sourcepub fn write_only(self, write_only: bool) -> Self
pub fn write_only(self, write_only: bool) -> Self
Mark this field as write-only (accepted in requests, not returned in responses).
§Example
use domainstack_schema::Schema;
let password = Schema::string()
.format("password")
.write_only(true);Examples found in repository?
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }Sourcepub fn deprecated(self, deprecated: bool) -> Self
pub fn deprecated(self, deprecated: bool) -> Self
Mark this field as deprecated.
§Example
use domainstack_schema::Schema;
let schema = Schema::string()
.deprecated(true)
.description("Use 'new_field' instead");Examples found in repository?
122 fn schema() -> Schema {
123 Schema::object()
124 .description("User account with request/response field modifiers")
125 .property(
126 "id",
127 Schema::string()
128 .read_only(true)
129 .description("Auto-generated user ID (returned in responses only)"),
130 )
131 .property(
132 "email",
133 Schema::string().format("email").description("User email"),
134 )
135 .property(
136 "password",
137 Schema::string()
138 .format("password")
139 .min_length(8)
140 .write_only(true)
141 .description("Password (accepted in requests only, never returned)"),
142 )
143 .property(
144 "createdAt",
145 Schema::string()
146 .format("date-time")
147 .read_only(true)
148 .description("Account creation timestamp"),
149 )
150 .property(
151 "oldUsername",
152 Schema::string()
153 .deprecated(true)
154 .description("Deprecated: Use 'email' instead"),
155 )
156 .required(&["email", "password"])
157 }Sourcepub fn extension<T: Serialize>(self, key: impl Into<String>, value: T) -> Self
pub fn extension<T: Serialize>(self, key: impl Into<String>, value: T) -> Self
Add a vendor extension (for validations that don’t map to OpenAPI).
Extension keys should start with “x-”.
§Example
use domainstack_schema::Schema;
use serde_json::json;
let schema = Schema::object()
.property("end_date", Schema::string().format("date"))
.extension("x-domainstack-validations", json!({
"cross_field": ["end_date > start_date"]
}));§Panics
Panics if the value cannot be serialized to JSON.
Use Self::try_extension for a non-panicking alternative.
Examples found in repository?
173 fn schema() -> Schema {
174 Schema::object()
175 .description("Date range with cross-field validation")
176 .property("startDate", Schema::string().format("date"))
177 .property("endDate", Schema::string().format("date"))
178 .required(&["startDate", "endDate"])
179 // Cross-field validation doesn't map to OpenAPI, so use vendor extension
180 .extension(
181 "x-domainstack-validations",
182 json!({
183 "cross_field": ["endDate > startDate"],
184 "description": "End date must be after start date"
185 }),
186 )
187 }
188}
189
190#[allow(dead_code)]
191struct OrderForm {
192 total: f64,
193 minimum_order: f64,
194 requires_minimum: bool,
195}
196
197impl ToSchema for OrderForm {
198 fn schema_name() -> &'static str {
199 "OrderForm"
200 }
201
202 fn schema() -> Schema {
203 Schema::object()
204 .description("Order form with conditional validation")
205 .property("total", Schema::number().minimum(0))
206 .property("minimumOrder", Schema::number().minimum(0))
207 .property("requiresMinimum", Schema::boolean())
208 .required(&["total", "minimumOrder", "requiresMinimum"])
209 // Conditional validation doesn't map to OpenAPI
210 .extension(
211 "x-domainstack-validations",
212 json!({
213 "conditional": {
214 "when": "requiresMinimum == true",
215 "then": "total >= minimumOrder"
216 },
217 "description": "When minimum is required, total must meet it"
218 }),
219 )
220 }