Custom Schema Definitions
While Serverpod automatically generates OpenAPI schemas from your Dart classes, there are cases where you might need to define custom schemas or override the generated ones. This page explains how to create and use custom schema definitions in your Serverpod Swagger documentation.
Why Use Custom Schemas?
Custom schemas are useful when you need to:
- Define complex data structures that don't have corresponding Dart classes
- Override the automatically generated schemas with more detailed information
- Add examples, descriptions, or constraints to your schemas
- Define schemas for third-party libraries or external systems
Creating Custom Schema Definitions
You can define custom schemas by creating a YAML file with your schema definitions. Create a file named openapi_schemas.yaml
in your project root:
1components:
2 schemas:
3 CustomResponse:
4 type: object
5 properties:
6 status:
7 type: string
8 enum: [success, error, pending]
9 description: The status of the operation
10 data:
11 type: object
12 description: The response data
13 nullable: true
14 message:
15 type: string
16 description: A human-readable message
17 required:
18 - status
19 PaginatedResult:
20 type: object
21 properties:
22 items:
23 type: array
24 items:
25 type: object
26 description: The list of items in the current page
27 total:
28 type: integer
29 format: int32
30 description: Total number of items
31 page:
32 type: integer
33 format: int32
34 description: Current page number
35 pageSize:
36 type: integer
37 format: int32
38 description: Number of items per page
39 required:
40 - items
41 - total
42 - page
43 - pageSize
The generator will include these schema definitions in the generated OpenAPI specification.
Referencing Custom Schemas in Endpoint Annotations
You can reference your custom schemas in endpoint annotations using the @Schema
annotation:
1/// Get paginated users
2///
3/// Returns a paginated list of users
4('/users')
5('GET')
6(response: 'PaginatedResult')
7Future<String> getUsers(Session session, {('page') int page = 1, ('pageSize') int pageSize = 10});
8
9/// Create user
10///
11/// Creates a new user and returns a custom response
12('/users')
13('POST')
14(response: 'CustomResponse')
15Future<String> createUser(Session session, User user);
In this example, the getUsers
endpoint returns a PaginatedResult
schema, and the createUser
endpoint returns a CustomResponse
schema.
Adding Examples to Custom Schemas
You can add examples to your custom schemas to help API consumers understand the expected data format:
1components:
2 schemas:
3 CustomResponse:
4 type: object
5 properties:
6 status:
7 type: string
8 enum: [success, error, pending]
9 description: The status of the operation
10 data:
11 type: object
12 description: The response data
13 nullable: true
14 message:
15 type: string
16 description: A human-readable message
17 required:
18 - status
19 example:
20 status: success
21 data:
22 id: 123
23 name: "John Doe"
24 message: "User created successfully"
Overriding Generated Schemas
If you want to override a schema that is automatically generated from a Dart class, simply define a schema with the same name in your YAML file:
1components:
2 schemas:
3 User:
4 type: object
5 properties:
6 id:
7 type: integer
8 format: int64
9 description: The unique identifier for the user
10 email:
11 type: string
12 format: email
13 description: The user's email address
14 name:
15 type: string
16 description: The user's full name
17 role:
18 type: string
19 enum: [admin, user, guest]
20 description: The user's role
21 required:
22 - email
23 - name
24 example:
25 id: 123
26 email: "john.doe@example.com"
27 name: "John Doe"
28 role: "user"
Using References in Schema Definitions
You can use references to reuse schema components within your definitions:
1components:
2 schemas:
3 Error:
4 type: object
5 properties:
6 code:
7 type: string
8 description: Error code
9 message:
10 type: string
11 description: Error message
12 required:
13 - code
14 - message
15
16 ApiResponse:
17 type: object
18 properties:
19 data:
20 type: object
21 nullable: true
22 description: Response data
23 error:
24 $ref: '#/components/schemas/Error'
25 description: Error information if the request failed
26 success:
27 type: boolean
28 description: Whether the request was successful
29 required:
30 - success
Combining Custom Schemas with Security Definitions
You can combine custom schemas with security definitions in a single YAML file:
1security:
2 - BearerAuth: []
3
4components:
5 securitySchemes:
6 BearerAuth:
7 type: http
8 scheme: bearer
9 bearerFormat: JWT
10 description: Enter your JWT token in the format 'Bearer {token}'
11
12 schemas:
13 ApiResponse:
14 type: object
15 properties:
16 data:
17 type: object
18 nullable: true
19 error:
20 type: object
21 nullable: true
22 properties:
23 code:
24 type: string
25 message:
26 type: string
27 success:
28 type: boolean
29 required:
30 - success