Skip to main content

itools_schema/
lib.rs

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