Skip to main content

wae_schema/
schema.rs

1//! Schema 定义与验证模块
2
3use serde::{Deserialize, Serialize};
4use serde_json;
5
6/// Schema 生成 trait
7///
8/// 实现此 trait 的类型可以自动生成 OpenAPI Schema。
9pub trait ToSchema {
10    /// 生成 Schema 定义
11    fn schema() -> Schema;
12}
13
14/// Schema 类型定义
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
16#[serde(rename_all = "lowercase")]
17pub enum SchemaType {
18    /// 字符串类型
19    String,
20    /// 整数类型
21    Integer,
22    /// 浮点数类型
23    Number,
24    /// 布尔类型
25    Boolean,
26    /// 数组类型
27    Array,
28    /// 对象类型
29    Object,
30    /// 空值类型
31    Null,
32}
33
34impl Default for SchemaType {
35    /// 创建默认的 Schema 类型(Object)
36    fn default() -> Self {
37        Self::Object
38    }
39}
40
41/// Schema 定义
42#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
43pub struct Schema {
44    /// Schema 标题
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub title: Option<String>,
47    /// Schema 描述
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub description: Option<String>,
50    /// Schema 类型
51    #[serde(rename = "type")]
52    pub schema_type: SchemaType,
53    /// 属性定义(仅 Object 类型)
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub properties: Option<std::collections::BTreeMap<String, Schema>>,
56    /// 必需属性列表
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub required: Option<Vec<String>>,
59    /// 数组元素类型(仅 Array 类型)
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub items: Option<Box<Schema>>,
62    /// 枚举值
63    #[serde(rename = "enum")]
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub enum_values: Option<Vec<serde_json::Value>>,
66    /// 默认值
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub default: Option<serde_json::Value>,
69    /// 示例值
70    #[serde(skip_serializing_if = "Option::is_none")]
71    pub example: Option<serde_json::Value>,
72    /// 是否可为空
73    #[serde(default)]
74    pub nullable: bool,
75    /// 只读
76    #[serde(default)]
77    pub read_only: bool,
78    /// 只写
79    #[serde(default)]
80    pub write_only: bool,
81    /// 最小值(Number/Integer)
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub minimum: Option<f64>,
84    /// 最大值(Number/Integer)
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub maximum: Option<f64>,
87    /// 最小长度(String)
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub min_length: Option<usize>,
90    /// 最大长度(String)
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub max_length: Option<usize>,
93    /// 正则模式(String)
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub pattern: Option<String>,
96    /// 格式(String)
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub format: Option<String>,
99    /// 多个类型(用于 oneOf)
100    #[serde(rename = "oneOf")]
101    #[serde(skip_serializing_if = "Option::is_none")]
102    pub one_of: Option<Vec<Schema>>,
103    /// 多个类型(用于 anyOf)
104    #[serde(rename = "anyOf")]
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub any_of: Option<Vec<Schema>>,
107    /// 多个类型(用于 allOf)
108    #[serde(rename = "allOf")]
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub all_of: Option<Vec<Schema>>,
111}
112
113impl Default for Schema {
114    /// 创建默认的 Schema(Object 类型)
115    fn default() -> Self {
116        Self {
117            title: None,
118            description: None,
119            schema_type: SchemaType::Object,
120            properties: None,
121            required: None,
122            items: None,
123            enum_values: None,
124            default: None,
125            example: None,
126            nullable: false,
127            read_only: false,
128            write_only: false,
129            minimum: None,
130            maximum: None,
131            min_length: None,
132            max_length: None,
133            pattern: None,
134            format: None,
135            one_of: None,
136            any_of: None,
137            all_of: None,
138        }
139    }
140}
141
142impl Schema {
143    /// 创建字符串 Schema
144    pub fn string() -> Self {
145        Self { schema_type: SchemaType::String, ..Default::default() }
146    }
147
148    /// 创建整数 Schema
149    pub fn integer() -> Self {
150        Self { schema_type: SchemaType::Integer, ..Default::default() }
151    }
152
153    /// 创建数字 Schema
154    pub fn number() -> Self {
155        Self { schema_type: SchemaType::Number, ..Default::default() }
156    }
157
158    /// 创建布尔 Schema
159    pub fn boolean() -> Self {
160        Self { schema_type: SchemaType::Boolean, ..Default::default() }
161    }
162
163    /// 创建数组 Schema
164    pub fn array(items: Schema) -> Self {
165        Self { schema_type: SchemaType::Array, items: Some(Box::new(items)), ..Default::default() }
166    }
167
168    /// 创建对象 Schema
169    pub fn object() -> Self {
170        Self { schema_type: SchemaType::Object, properties: Some(std::collections::BTreeMap::new()), ..Default::default() }
171    }
172
173    /// 设置标题
174    pub fn title(mut self, title: impl Into<String>) -> Self {
175        self.title = Some(title.into());
176        self
177    }
178
179    /// 设置描述
180    pub fn description(mut self, desc: impl Into<String>) -> Self {
181        self.description = Some(desc.into());
182        self
183    }
184
185    /// 添加属性
186    pub fn property(mut self, name: impl Into<String>, schema: Schema) -> Self {
187        let properties = self.properties.get_or_insert_with(std::collections::BTreeMap::new);
188        properties.insert(name.into(), schema);
189        self
190    }
191
192    /// 设置必需属性
193    pub fn required(mut self, fields: Vec<&str>) -> Self {
194        self.required = Some(fields.into_iter().map(String::from).collect());
195        self
196    }
197
198    /// 设置枚举值
199    pub fn enum_values(mut self, values: Vec<serde_json::Value>) -> Self {
200        self.enum_values = Some(values);
201        self
202    }
203
204    /// 设置默认值
205    pub fn with_default(mut self, value: serde_json::Value) -> Self {
206        self.default = Some(value);
207        self
208    }
209
210    /// 设置示例值
211    pub fn example(mut self, value: serde_json::Value) -> Self {
212        self.example = Some(value);
213        self
214    }
215
216    /// 设置格式
217    pub fn format(mut self, format: impl Into<String>) -> Self {
218        self.format = Some(format.into());
219        self
220    }
221
222    /// 设置正则模式
223    pub fn pattern(mut self, pattern: impl Into<String>) -> Self {
224        self.pattern = Some(pattern.into());
225        self
226    }
227
228    /// 设置最小长度
229    pub fn min_length(mut self, len: usize) -> Self {
230        self.min_length = Some(len);
231        self
232    }
233
234    /// 设置最大长度
235    pub fn max_length(mut self, len: usize) -> Self {
236        self.max_length = Some(len);
237        self
238    }
239
240    /// 设置最小值
241    pub fn minimum(mut self, min: f64) -> Self {
242        self.minimum = Some(min);
243        self
244    }
245
246    /// 设置最大值
247    pub fn maximum(mut self, max: f64) -> Self {
248        self.maximum = Some(max);
249        self
250    }
251
252    /// 设置可为空
253    pub fn nullable(mut self, nullable: bool) -> Self {
254        self.nullable = nullable;
255        self
256    }
257
258    /// 设置只读
259    pub fn read_only(mut self, read_only: bool) -> Self {
260        self.read_only = read_only;
261        self
262    }
263
264    /// 设置只写
265    pub fn write_only(mut self, write_only: bool) -> Self {
266        self.write_only = write_only;
267        self
268    }
269
270    /// 设置 oneOf
271    pub fn one_of(mut self, schemas: Vec<Schema>) -> Self {
272        self.one_of = Some(schemas);
273        self
274    }
275
276    /// 设置 anyOf
277    pub fn any_of(mut self, schemas: Vec<Schema>) -> Self {
278        self.any_of = Some(schemas);
279        self
280    }
281
282    /// 设置 allOf
283    pub fn all_of(mut self, schemas: Vec<Schema>) -> Self {
284        self.all_of = Some(schemas);
285        self
286    }
287
288    /// 转换为 JSON Schema
289    pub fn to_json_schema(&self) -> serde_json::Value {
290        serde_json::to_value(self).unwrap_or(serde_json::Value::Null)
291    }
292}
293
294// 基础类型的 ToSchema 实现
295impl ToSchema for String {
296    fn schema() -> Schema {
297        Schema::string()
298    }
299}
300
301impl ToSchema for i64 {
302    fn schema() -> Schema {
303        Schema::integer()
304    }
305}
306
307impl ToSchema for i32 {
308    fn schema() -> Schema {
309        Schema::integer()
310    }
311}
312
313impl ToSchema for i16 {
314    fn schema() -> Schema {
315        Schema::integer()
316    }
317}
318
319impl ToSchema for i8 {
320    fn schema() -> Schema {
321        Schema::integer()
322    }
323}
324
325impl ToSchema for u64 {
326    fn schema() -> Schema {
327        Schema::integer()
328    }
329}
330
331impl ToSchema for u32 {
332    fn schema() -> Schema {
333        Schema::integer()
334    }
335}
336
337impl ToSchema for u16 {
338    fn schema() -> Schema {
339        Schema::integer()
340    }
341}
342
343impl ToSchema for u8 {
344    fn schema() -> Schema {
345        Schema::integer()
346    }
347}
348
349impl ToSchema for f64 {
350    fn schema() -> Schema {
351        Schema::number()
352    }
353}
354
355impl ToSchema for f32 {
356    fn schema() -> Schema {
357        Schema::number()
358    }
359}
360
361impl ToSchema for bool {
362    fn schema() -> Schema {
363        Schema::boolean()
364    }
365}
366
367impl<T: ToSchema> ToSchema for Vec<T> {
368    fn schema() -> Schema {
369        Schema::array(T::schema())
370    }
371}
372
373impl<T: ToSchema> ToSchema for Option<T> {
374    fn schema() -> Schema {
375        T::schema().nullable(true)
376    }
377}
378
379impl ToSchema for serde_json::Value {
380    fn schema() -> Schema {
381        <Schema as Default>::default()
382    }
383}