This proposal aims to introduce example annotations in the OpenAPI tool. This feature will enable rendering example schemas in the generated OpenAPI specification.
Goals
Provide a way to add example(s) for the Ballerina types and the resource function parameters
Provide validation for the examples with respect to the attached type
Generate example schemas in the OpenAPI specification with the values provided in the annotation
Non-Goals
Provide a way to add a file path or external link(See External Examples in Adding Examples) for a example value
Provide a way to automatically generate example and add it in the example annotation
Motivation
The OpenAPI specification allows adding examples to parameters, properties and objects. These examples can be read by the tools and the libraries that process the OpenAPI specification. For example, the Ballerina OpenAPI tool can use the examples to generate the mock client or server.
Note: Once this proposed annotations are introduced we need to adjust the mock client generation and we have a way to represent the examples in the OpenAPI spec to the generated service/client.
Description
Proposed design
The examples can be specified in the following two ways in the OpenAPI specification:
The example schema, which represents a single example
The examples schema, which represents multiple examples with distinct key values
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
examples:
Jessica: # Example 1
value:
id: 10
name: Jessica Smith
Ron: # Example 2
value:
id: 11
name: Ron Stewart
The above scenarios will be addressed via two different annotations in the Ballerina OpenAPI tool:
The @openapi:Example annotation
@openapi:Example {
value: {
id: 10,
name: "Jessica Smith"
}
}
type User record {
int id;
string name
}
The @openapi:Examples annotation
@openapi:Examples {
Jessica: { // Example 1
value: {
id: 10,
name: "Jessica Smith"
}
},
Ron: { // Example 2
value: {
id: 11,
name: "Ron Stewart"
}
}
}
type User record {
int id;
string name
}
The example and examples schemas can be specified in objects, individual properties and operation parameters. This is supported by enabling the ballerina annotation on the Ballerina types, record fields and resource function parameter.
Note:
The example annotations are not allowed on the request parameter when it has a union type which cannot represented by a single media-type. In that case, it is not possible to infer the corresponding media-type of the example.
In addition to that, the example annotations are not supported in the response return type since it can have multiple status code response with multiple media-types.
The types can be imported from external ballerina packages and the examples from these annotations should be accessed in the compiler plugin. For that requirement, the annotations are designed as constant annotations.
The proposed annotation definitions look like this:
type ExampleValue record {|
anydata value;
|};
type ExampleValues record {|
ExampleValue...;
|};
const annotation ExampleValue Example on type, parameter, record field;
const annotation ExampleValues Examples on paramete;
The examples schemas will be added as follows:
Annotation attachment point
Behaviour
type
Examples will be added to the type schema
parameter (request payload)
Examples will be added to the media-type field of the request body
parameter (other)
Examples will be added to the parameter schema
record field
Examples will be added to the corresponding property schema
Compiler validation
Validate whether the provided example value matches the type
Validate the example annotation usage in the request parameter
Restrict the usage of both annotations: @openapi:Example/@openapi:Examples on the same parameter
Examples
Parameter example:
Ballerina representation:
resource function get path(
@openapi:Example{value: "approved"}
"approved"|"pending"|"closed"|"new" status) {}
resource function post users(
@openapi:Example {
value: {
id: 10,
name: Jessica Smith
}
}
record{int id; string name;} payload) returns http:Ok {}
Generated Schema:
paths:
/users:
post:
summary: Adds a new user
requestBody:
content:
application/json:
schema: # Request body contents
type: object
properties:
id:
type: integer
name:
type: string
example: # Sample object
id: 10
name: Jessica Smith
responses:
'200':
description: OK
Request body example with reference:
Ballerina representation:
resource function post users(
@openapi:Example {
value: {
id: 10,
name: Jessica Smith
}
} User payload) returns http:Ok {}
Generated Schema:
paths:
/users:
post:
summary: Adds a new user
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/User'
example:
id: 10
name: Jessica Smith
responses:
'200':
description: OK
Property level example:
Ballerina representation:
type User record {
@openapi:Example { value: 1 }
int id;
@openapi:Example { value: "Jessica Smith" }
string name;
}
Generated Schema:
components:
schemas:
User: # Schema name
type: object
properties:
id:
type: integer
format: int64
example: 1 # Property example
name:
type: string
example: Jessica Smith # Property example
Object level example:
Ballerina representation:
@openapi:Example {
value: {
id: 1,
name: "Jessica Smith"
}
}
type User record {
int id;
string name;
}
Generated Schema:
components:
schemas:
User: # Schema name
type: object
properties:
id:
type: integer
name:
type: string
example: # Object-level example
id: 1
name: Jessica Smith
Provide a way to add a file path or external link for a example value:
This can be done by adding a union type for the annotation type. This has to be checked with the Ballerina lang team:
type ExamplePath record {|
string path;
|};
type ExampleReference record {|
string ref;
|};
const annotation ExampleValue|ExamplePath|ExampleReference Example on type, parameter, record field;
Provide a way to automatically generate example and add it in the example annotation:
When the type is complex, it is not practical to add an example manually. So it will be better to generate a sample example using a code action or generate one with Ballerina AI tool.
In addition to that, Ballerina tooling supports creating records from JSON examples. We could use that to automatically inject the example annotation when a record is created from JSON.
Summary
This proposal aims to introduce example annotations in the OpenAPI tool. This feature will enable rendering example schemas in the generated OpenAPI specification.
Goals
Non-Goals
External Examples
in Adding Examples) for a example valueMotivation
The OpenAPI specification allows adding examples to parameters, properties and objects. These examples can be read by the tools and the libraries that process the OpenAPI specification. For example, the Ballerina OpenAPI tool can use the examples to generate the mock client or server.
Description
Proposed design
The examples can be specified in the following two ways in the OpenAPI specification:
The
example
schema, which represents a single exampleThe
examples
schema, which represents multiple examples with distinct key valuesThe above scenarios will be addressed via two different annotations in the Ballerina OpenAPI tool:
The
@openapi:Example
annotationThe
@openapi:Examples
annotationThe
example
andexamples
schemas can be specified in objects, individual properties and operation parameters. This is supported by enabling the ballerina annotation on the Ballerina types, record fields and resource function parameter.The types can be imported from external ballerina packages and the examples from these annotations should be accessed in the compiler plugin. For that requirement, the annotations are designed as constant annotations.
The proposed annotation definitions look like this:
The examples schemas will be added as follows:
media-type
field of the request bodyCompiler validation
@openapi:Example
/@openapi:Examples
on the same parameterExamples
Parameter example:
Ballerina representation:
Generated Schema:
Request body example with inline object schema:
Ballerina representation:
Generated Schema:
Request body example with reference:
Ballerina representation:
Generated Schema:
Property level example:
Ballerina representation:
Generated Schema:
Object level example:
Ballerina representation:
Generated Schema:
Array example:
Ballerina representation:
Generated Schema:
References
Future Works
Provide a way to add a file path or external link for a example value:
This can be done by adding a union type for the annotation type. This has to be checked with the Ballerina lang team:
Provide a way to automatically generate example and add it in the example annotation:
When the type is complex, it is not practical to add an example manually. So it will be better to generate a sample example using a code action or generate one with Ballerina AI tool. In addition to that, Ballerina tooling supports creating records from JSON examples. We could use that to automatically inject the example annotation when a record is created from JSON.